#include "InitWin.h"
#include "../MSPIX/MSPIX.h"
#include "../matrix/seg_matrix.h"

unsigned char g_p_rough_map[IMG_MAX_SIZE * IMG_MAX_SIZE * 3];
unsigned char g_p_af_map[IMG_MAX_SIZE * IMG_MAX_SIZE * 3];

//FrameworkA===================================================================
static int g_p_fore_hist[HIST_BIN_NUM][HIST_BIN_NUM][HIST_BIN_NUM];
static int g_p_back_hist[HIST_BIN_NUM][HIST_BIN_NUM][HIST_BIN_NUM];
static int g_fore_size;
static int g_back_size;
short g_candidate_win[S_PIX_NUM][4];
short g_candidate_id[S_PIX_NUM];
short g_candidate_num;
float g_box_merge_matrix[S_PIX_NUM][S_PIX_NUM];

//FrameworkB===================================================================
static unsigned int g_p_distance_matrix[S_PIX_NUM][S_PIX_NUM];
static unsigned int g_p_clusters_matrix[S_PIX_NUM][S_PIX_NUM];
static int g_p_fg_flag_array[S_PIX_NUM];
static int g_p_rank_array[S_PIX_NUM];

static float g_p_fg_bg_dis_matrix[S_PIX_NUM][S_PIX_NUM];
float g_p_conf_vector[S_PIX_NUM];

static float g_p_size_priori[31];

static void create_rough_map_by_mspix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y, int box_state);
static void create_rough_map_by_init_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y);
static void low_contrast_judge      (unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y);
static void run_back_ground_classify(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y);
static void create_bg_and_fg_hist_by_mspix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, short* p_bg_box);
static int count_fg_number(sp_output* p_sp);


void init_fg_bg_flag(sp_output* p_sp)
{
	int sum_count = 0;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[i].is_bg = false;
		p_sp->p_spix[i].is_fg = true;
		 p_sp->p_spix[i].salient_conf = 0;
		if (p_sp->p_spix[i].size < 20)
		{
			p_sp->p_spix[i].is_bg = true;
			sum_count++;
		}
		else
		{
			p_sp->p_spix[i].is_bg = false;
		}
	}
	int sun = 0;

	g_p_size_priori[0] = 0.134288468;
	g_p_size_priori[1] = 0.360611486;
	g_p_size_priori[2] = 0.512416004;

	g_p_size_priori[3] = 0.563480827;
	g_p_size_priori[4] = 0.583312414;

	g_p_size_priori[5] = 0.577912715;
	g_p_size_priori[6] = 0.587008276;
	g_p_size_priori[7] = 0.542324381;
	g_p_size_priori[8] = 0.517769887;
	g_p_size_priori[9] = 0.498571122;
	g_p_size_priori[10] = 0.463565179;
	g_p_size_priori[11] = 0.44259777;
	g_p_size_priori[12] = 0.399082212;
	g_p_size_priori[13] = 0.385625681;
	g_p_size_priori[14] = 0.37682234;
	g_p_size_priori[15] = 0.331199102;
	g_p_size_priori[16] = 0.358865132;
	g_p_size_priori[17] = 0.30890734;
	g_p_size_priori[18] = 0.303236906;
	g_p_size_priori[19] = 0.249939002;
	g_p_size_priori[20] = 0.283985535;
	g_p_size_priori[21] = 0.218430475;
	g_p_size_priori[22] = 0.244560825;
	g_p_size_priori[23] = 0.238802418;
	g_p_size_priori[24] = 0.176733563;
	g_p_size_priori[25] = 0.159696802;
	g_p_size_priori[26] = 0.176733563;
	g_p_size_priori[27] = 0.176733563;
	g_p_size_priori[28] = 0.134288468;
	g_p_size_priori[29] = 0.124288468;
	g_p_size_priori[30] = 0.119912573;
}

float intersection_conf(short* p_win_touch, short* p_win_other)
{
	short p_inter_win[4];

	p_inter_win[0] = p_win_touch[0];
	if (p_inter_win[0] < p_win_other[0])
	{
		p_inter_win[0] = p_win_other[0];
	}

	p_inter_win[1] = p_win_touch[1];
	if (p_inter_win[1] < p_win_other[1])
	{
		p_inter_win[1] = p_win_other[1];
	}

	p_inter_win[2] = p_win_touch[2];
	if (p_inter_win[2] > p_win_other[2])
	{
		p_inter_win[2] = p_win_other[2];
	}

	p_inter_win[3] = p_win_touch[3];
	if (p_inter_win[3] > p_win_other[3])
	{
		p_inter_win[3] = p_win_other[3];
	}

	if (p_inter_win[2] < p_inter_win[0] || p_inter_win[3] < p_inter_win[1])
	{
		return 0.0f;
	}
	else
	{
		int size_inter = (p_inter_win[2] - p_inter_win[0] + 1) * (p_inter_win[3] - p_inter_win[1] + 1);
		int size_touch = (p_win_touch[2] - p_win_touch[0] + 1) * (p_win_touch[3] - p_win_touch[1] + 1);
		float inter_rate = (float)size_inter / (float)size_touch;
		return inter_rate;
	}
}

float coverage_between_2boxs(short* p_win_A, short* p_win_B)
{
	short p_inter_win[4];

	p_inter_win[0] = p_win_A[0];
	if (p_inter_win[0] < p_win_B[0])
	{
		p_inter_win[0] = p_win_B[0];
	}

	p_inter_win[1] = p_win_A[1];
	if (p_inter_win[1] < p_win_B[1])
	{
		p_inter_win[1] = p_win_B[1];
	}

	p_inter_win[2] = p_win_A[2];
	if (p_inter_win[2] > p_win_B[2])
	{
		p_inter_win[2] = p_win_B[2];
	}

	p_inter_win[3] = p_win_A[3];
	if (p_inter_win[3] > p_win_B[3])
	{
		p_inter_win[3] = p_win_B[3];
	}

	if (p_inter_win[2] < p_inter_win[0] || p_inter_win[3] < p_inter_win[1])
	{
		return 0.0f;
	}
	else
	{
		int inter_size = (p_inter_win[2] - p_inter_win[0]) * (p_inter_win[3] - p_inter_win[1]);

		int win_A_size = (p_win_A[2] - p_win_A[0]) * (p_win_A[3] - p_win_A[1]);
		int win_B_size = (p_win_B[2] - p_win_B[0]) * (p_win_B[3] - p_win_B[1]);
		int union_size =  win_A_size + win_B_size - inter_size + 1;

		float intersection_rate = (float)inter_size / (float)union_size;

		return intersection_rate;
	}
}


void choose_best_box(short p_wins[][4], int win_num, short* p_final_win, float* p_af_conf, int touch_x, int touch_y)
{
	 // for (int wi = 0; wi < 18; wi++)
	 // {
		//  printf("p_wins[%d][0] = %d\n",  wi, p_wins[wi][0]);
		//  printf("p_wins[%d][1] = %d\n",  wi, p_wins[wi][1]);
		//  printf("p_wins[%d][2] = %d\n",  wi, p_wins[wi][2]);
		//  printf("p_wins[%d][3] = %d\n",  wi, p_wins[wi][3]);
		//  printf("\n");
	 // }


	//if (p_wins[13][2] - p_wins[13][0] > 50 && 
	//	p_wins[13][3] - p_wins[13][1] > 50)
	//{
	//	for (int i = 0; i < 4; i++)
	//	{
	//		p_final_win[i] = p_wins[13][i];
	//	}
	//	return;
	//}


	float coverage_qvga = 0.0f;
	int coverage_count = 1;
	for (int m = 0; m < win_num/2; m++)
	{
		short* p_win_A = p_wins[m];
		if (p_win_A[0] == p_win_A[2] || p_win_A[1] == p_win_A[3])
		{
			continue;
		}
		for (int n = 0; n < win_num/2; n++)
		{
			short* p_win_B = p_wins[n];
			if (m == n || p_win_B[0] == p_win_B[2] || p_win_B[1] == p_win_B[3])
			{
				continue;
			}
			coverage_qvga += coverage_between_2boxs(p_win_A, p_win_B);
			coverage_count++;
		}
	}
	coverage_qvga = coverage_qvga / (float)(coverage_count);

	float coverage_qqvga = 0.0f;
	coverage_count = 1;
	for (int m = win_num/2; m < win_num; m++)
	{
		short* p_win_A = p_wins[m];
		if (p_win_A[0] == p_win_A[2] || p_win_A[1] == p_win_A[3])
		{
			continue;
		}
		for (int n = win_num/2; n < win_num; n++)
		{
			short* p_win_B = p_wins[n];
			if (m == n || p_win_B[0] == p_win_B[2] || p_win_B[1] == p_win_B[3])
			{
				continue;
			}
			coverage_qqvga += coverage_between_2boxs(p_win_A, p_win_B);
			coverage_count++;
		}
	}
	coverage_qqvga = coverage_qqvga / (float)(coverage_count);



	//===========================================================================
	if (coverage_qqvga == coverage_qvga && coverage_qqvga == 0.0f)
	{
		int qqvga_size_sum = 0;
		int qvga_size_sum  = 0;

		int qqvga_max_id = 13;
		int qqvga_max_size = -1;

		int qvga_max_id = 4;
		int qvga_max_size = -1;

		for (int m = 0; m < win_num/2; m++)
		{
			int qvga_size = (p_wins[m][2] - p_wins[m][0]) * (p_wins[m][3] - p_wins[m][1]);
			qvga_size_sum  += qvga_size;
			if (qvga_size > qvga_max_size)
			{
				qvga_max_size = qvga_size;
				qvga_max_id   = m;
			}
		}
		for (int m = win_num/2; m < win_num; m++)
		{
			int qqvga_size = (p_wins[m][2] - p_wins[m][0]) * (p_wins[m][3] - p_wins[m][1]);
			qqvga_size_sum += qqvga_size;
			if (qqvga_size > qqvga_max_size)
			{
				qqvga_max_size = qqvga_size;
				qqvga_max_id   = m;
			}
		}

		if (qvga_size_sum < qqvga_size_sum && qvga_size_sum > 0)
		{
			for (int i = 0; i < 4; i++)
			{
				p_final_win[i] = p_wins[qvga_max_id][i];
			}
			return;
		}
		else if (qvga_size_sum >= qqvga_size_sum && qvga_size_sum > 0)
		{
			for (int i = 0; i < 4; i++)
			{
				p_final_win[i] = p_wins[qqvga_max_id][i];
			}
			return;
		}
		else if(qvga_size_sum == qqvga_size_sum && qvga_size_sum == 0)
		{
			p_final_win[0] = touch_x - 20;
			p_final_win[1] = touch_y - 20;
			p_final_win[2] = touch_x + 20;
			p_final_win[3] = touch_y + 20;
			return;
		}
	}
	else
	{
		if (p_wins[13][2] - p_wins[13][0] > 50 && 
			p_wins[13][3] - p_wins[13][1] > 50)
		{
			if (touch_x > p_wins[13][0] && touch_x < p_wins[13][2] && 
				touch_y > p_wins[13][1] && touch_y < p_wins[13][3])
			{
				for (int i = 0; i < 4; i++)
				{
					p_final_win[i] = p_wins[13][i];
				}
				return;
			}
		}
	}
	//===========================================================================




	if (coverage_qqvga == 0.0f && coverage_qvga == 0.0f)
	{
		p_final_win[0] = touch_x - 20;
		p_final_win[1] = touch_y - 20;
		p_final_win[2] = touch_x + 20;
		p_final_win[3] = touch_y + 20;
		return;
	}


	int final_start_id = 0;
	int final_end_id   = win_num;


	if (coverage_qvga >= coverage_qqvga)
	{
		final_start_id = 0;
		final_end_id   = win_num / 2;
	}
	else
	{
		final_start_id = win_num / 2;
		final_end_id   = win_num;
	}

	//final_start_id = win_num / 2;
	//final_end_id   = win_num;

	final_start_id = 0;
	final_end_id   = win_num;

	for (int i = 0; i < 4; i++)
	{
		p_final_win[i] = 0;
	}

	int count = 0;
	int refine_radius = 10; //10
	for (int wi = final_start_id; wi < final_end_id; wi++)
	{
		if (p_wins[wi][0] == p_wins[wi][2] || p_wins[wi][1] == p_wins[wi][3])
		{
			continue;
		}
		if (touch_x < p_wins[wi][0] - refine_radius || touch_x > p_wins[wi][2] + refine_radius || 
			touch_y < p_wins[wi][1] - refine_radius || touch_y > p_wins[wi][3] + refine_radius)
		{
			continue;
		}

		for (int j = 0; j < 4; j++)
		{
			p_final_win[j] += p_wins[wi][j];
		}
		count++;
	}

	if (count == 0)
	{
		p_final_win[0] = touch_x - 20;
		p_final_win[1] = touch_y - 20;
		p_final_win[2] = touch_x + 20;
		p_final_win[3] = touch_y + 20;
		return;
	}


	for (int i = 0; i < 4; i++)
	{
		p_final_win[i] = (float)p_final_win[i] / (float)count;
	}

	int interate_count = 10;
	while (interate_count > 1)
	{
		float weights[18] = {0.0f};
		float sum = 0.0f;
		float avg = 0.0f;
		float weight_count = 1.0f;
		for (int wi = final_start_id; wi < final_end_id; wi++)
		{
			if (p_wins[wi][0] == p_wins[wi][2] || p_wins[wi][1] == p_wins[wi][3])
			{
				weights[wi] = 0.0f;
				continue;
			}
			weights[wi] = coverage_between_2boxs(p_final_win, p_wins[wi]);
			sum += weights[wi];
			weight_count++;
		}
		avg = sum / weight_count;

		for (int i = 0; i < 4; i++)
		{
			p_final_win[i] = 0;
		}

		sum = 0.0f;
		for (int wi = final_start_id; wi < final_end_id; wi++)
		{
			//if (weights[wi] >= avg)
			if (weights[wi] >= 0)
			{
				for (int i = 0; i < 4; i++)
				{
					p_final_win[i] += (short)(weights[wi] * (float)p_wins[wi][i] + 0.5f);
				}
				sum += weights[wi];
			}
		}

		for (int i = 0; i < 4; i++)
		{
			p_final_win[i] = (short)((float)p_final_win[i] / sum + 0.5f);
		}
		interate_count--;
	}


	//if (p_wins[13][0] == p_wins[13][2] || p_wins[13][1] == p_wins[13][3])
	//{
	//	for (int j = 0; j < 4; j++)
	//	{
	//		p_final_win[0] = touch_x - 20;
	//		p_final_win[1] = touch_y - 20;
	//		p_final_win[2] = touch_x + 20;
	//		p_final_win[3] = touch_y + 20;
	//	}
	//}
	//else
	//{
	//	for (int i = 0; i < 4; i++)
	//	{
	//		p_final_win[i] = p_wins[13][i];
	//	}
	//}
}


float distance_conf(int s1_x, int s2_x, int s1_y, int s2_y, int img_width, int img_height)
{
	int dis = (s1_x - s2_x) * (s1_x - s2_x) + (s1_y - s2_y) * (s1_y - s2_y);
	float dis_conf = 1.0f - (float) 130 * dis / (float) (img_width* img_width + img_height*img_height);  //120
	if (dis_conf < 0)
	{
		dis_conf = 0;
	}
	return dis_conf;
}


float distance_dis(int s1_x, int s2_x, int s1_y, int s2_y, int img_width, int img_height)
{
	int dis = (s1_x - s2_x) * (s1_x - s2_x) + (s1_y - s2_y) * (s1_y - s2_y);
	if (dis > 1000)
	{
		dis = 9999999.0f;
	}
	return dis;
}


float color_conf(int s1_color0, int s1_color1, int s1_color2, int s2_color0, int s2_color1, int s2_color2)
{
	int dis = (s1_color0 - s2_color0)*(s1_color0 - s2_color0) + (s1_color1 - s2_color1)*(s1_color1 - s2_color1) + (s1_color2 - s2_color2)*(s1_color2 - s2_color2);
	float dis_conf = 1.0f - (float) dis / (float) (255 * 255 * 3);

	//int dis = (s1_color1 - s2_color1)*(s1_color1 - s2_color1) + (s1_color2 - s2_color2)*(s1_color2 - s2_color2);
	//float dis_conf = 1.0f - (float) dis / (float) (255 * 255 * 2);

	return dis_conf;
}

float color_dis(int s1_color0, int s1_color1, int s1_color2, int s2_color0, int s2_color1, int s2_color2)
{
	int dis = (s1_color0 - s2_color0)*(s1_color0 - s2_color0) + (s1_color1 - s2_color1)*(s1_color1 - s2_color1) + (s1_color2 - s2_color2)*(s1_color2 - s2_color2);
	return dis;
}

int win_size(short* p_win)
{
	int size = (p_win[2] - p_win[0] + 1) * (p_win[3] - p_win[1] + 1);
	if (size <= 0)
	{
		size = 1;
	}
	return size;
}


void computer_size_conf(sp_output* p_sp, int valid_s_pix_num, int touch_label, int img_width, int img_height)
{
	int image_size = img_width * img_height;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		int size = win_size(p_sp->p_spix[si].win);
		//p_sp->p_spix[si].size_conf = (float)p_sp->p_spix[si].size / (float)size;

		int size_id = (int)((sqrtf((float)size) * 4.0f) / 20.0);
		p_sp->p_spix[si].size_conf = g_p_size_priori[size_id];


		if (p_sp->p_spix[si].size_conf < 0.1)
		{
			p_sp->p_spix[si].size_conf = 0;
		}

		if (size > image_size * 0.9f)
		{
			p_sp->p_spix[si].size_conf = 0.0f;
		}

		if (p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0] > 0.9 * img_width)
		{
			p_sp->p_spix[si].size_conf = 0.0f;
		}

		if (p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1] > 0.9 * img_height)
		{
			p_sp->p_spix[si].size_conf = 0.0f;
		}
	}

	//printf("touch_label size_conf = %f\n", p_sp->p_spix[touch_label].size_conf);

	if (p_sp->p_spix[touch_label].size_conf > 0.7 && p_sp->p_spix[touch_label].size > image_size * 0.001)
	{
		for (int si = 0; si < valid_s_pix_num; si++)
		{
			p_sp->p_spix[si].size_conf = 0.0f;
		}
		p_sp->p_spix[touch_label].size_conf = 1.0f;
	}

	//if (touch_label != max_id)
	//{
	//	p_sp->p_spix[max_id].size_conf = 0.0f;
	//}
}

void compute_inter_conf(sp_output* p_sp, int valid_s_pix_num, int touch_label)
{
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].inter_conf = intersection_conf(p_sp->p_spix[touch_label].win, p_sp->p_spix[si].win);
	}
}

void compute_spital_conf(sp_output* p_sp, int valid_s_pix_num, int touch_x, int touch_y, int img_width, int img_height, int touch_label)
{
	//touch_x = p_sp->p_spix[touch_label].X;
	//touch_y = p_sp->p_spix[touch_label].Y;

	for (int si = 0; si < valid_s_pix_num; si++)
	{

		p_sp->p_spix[si].dis_conf = distance_conf(touch_x, p_sp->p_spix[si].X, touch_y, p_sp->p_spix[si].Y, img_width, img_height);

		if (p_sp->layer_id == 0)
		{
			p_sp->p_spix[si].dis_conf = 1.0f;
		}
	}
}



void compute_color_conf(sp_output* p_sp, int valid_s_pix_num, int touch_label)
{
	int avg[3] = {0};
	int count = 0;

	//for (int si = 0; si < valid_s_pix_num; si++)
	//{
	//	if (p_sp->p_spix[si].inter_conf > 0)
	//	{
	//		avg[0] += p_sp->p_spix[si].color.c0;
	//		avg[1] += p_sp->p_spix[si].color.c1;
	//		avg[2] += p_sp->p_spix[si].color.c2;
	//		count++;
	//	}
	//}
	//avg[0] = (int)((float)avg[0] / (float)count + 0.5f);
	//avg[1] = (int)((float)avg[1] / (float)count + 0.5f);
	//avg[2] = (int)((float)avg[2] / (float)count + 0.5f);

	avg[0] = p_sp->p_spix[touch_label].color.c0;
	avg[1] = p_sp->p_spix[touch_label].color.c1;
	avg[2] = p_sp->p_spix[touch_label].color.c2;

	float avg_dis = 0.0f;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].color_conf  =  color_conf(p_sp->p_spix[si].color.c0, p_sp->p_spix[si].color.c1, p_sp->p_spix[si].color.c2, avg[0], avg[1], avg[2]);
		//printf("spix[%d] color_conf = %f\n", si, p_sp->p_spix[si].color_conf);
		avg_dis += p_sp->p_spix[si].color_conf;
	}
	avg_dis /= (float)(valid_s_pix_num);


	//printf("avg_dis = %f\n",avg_dis);
	if (avg_dis < 0.96)
	{
		avg_dis = 0.96;
	}

	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].color_conf < avg_dis)
		{
			p_sp->p_spix[si].color_conf = 0.0f;
		}
	}
}




void merge_candidate_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	short p_box_final[4] = {0};
	p_box_final[0] = img_width;
	p_box_final[1] = img_height;
	p_box_final[2] = -1;
	p_box_final[3] = -1;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_fg == true && p_sp->p_spix[si].is_bg == false)
		{
			if (p_box_final[0] > p_sp->p_spix[si].win[0])
			{
				p_box_final[0] = p_sp->p_spix[si].win[0];
			}
			if (p_box_final[2] < p_sp->p_spix[si].win[2])
			{
				p_box_final[2] = p_sp->p_spix[si].win[2];
			}
			if (p_box_final[1] > p_sp->p_spix[si].win[1])
			{
				p_box_final[1] = p_sp->p_spix[si].win[1];
			}
			if (p_box_final[3] < p_sp->p_spix[si].win[3])
			{
				p_box_final[3] = p_sp->p_spix[si].win[3];
			}
		}
	}
	for (int i = 0; i < 4; i++)
	{
		p_sp->final_win[i] = p_box_final[i];
	}

	if (p_sp->final_win[0] > img_width - 2)
	{
		p_sp->final_win[0] = img_width - 2;
	}
	else if(p_sp->final_win[0] <= 0)
	{
		p_sp->final_win[0] = 0;
	}

	if (p_sp->final_win[2] > img_width - 2)
	{
		p_sp->final_win[2] = img_width - 2;
	}
	else if(p_sp->final_win[2] <= 0)
	{
		p_sp->final_win[2] = 0;
	}

	if (p_sp->final_win[1] > img_height - 2)
	{
		p_sp->final_win[1] = img_height - 2;
	}
	else if(p_sp->final_win[1] <= 0)
	{
		p_sp->final_win[1] = 0;
	}


	if (p_sp->final_win[3] > img_height - 2)
	{
		p_sp->final_win[3] = img_height - 2;
	}
	else if(p_sp->final_win[3] <= 0)
	{
		p_sp->final_win[3] = 0;
	}
}


void computer_salient_conf(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int valid_s_pix_num, int touch_x, int touch_y, int iterate_count)
{

	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	int p_touch_color[3] = {0};
	p_touch_color[0] = p_sp->p_spix[touch_label].color.c0;
	p_touch_color[1] = p_sp->p_spix[touch_label].color.c1;
	p_touch_color[2] = p_sp->p_spix[touch_label].color.c2;




	float touch_dis = 0.0f;
	float color_dis = 0.0f;
	int dis_0, dis_1, dis_2;


	int dis_x, dis_y;
	float spatial_dis = 0.0f;

	float max_color_dis = -1, min_color_dis = 256;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		dis_0 = (p_sp->p_spix[si].color.c0 - p_touch_color[0]) * (p_sp->p_spix[si].color.c0 - p_touch_color[0]);
		dis_1 = (p_sp->p_spix[si].color.c1 - p_touch_color[1]) * (p_sp->p_spix[si].color.c1 - p_touch_color[1]);
		dis_2 = (p_sp->p_spix[si].color.c2 - p_touch_color[2]) * (p_sp->p_spix[si].color.c2 - p_touch_color[2]);
		touch_dis  = (COLOR_MODIFY_RATE * dis_0 + dis_1 + dis_2);

		dis_x = (p_sp->p_spix[si].X - touch_x) * (p_sp->p_spix[si].X - touch_x);
		dis_y = (p_sp->p_spix[si].Y - touch_y) * (p_sp->p_spix[si].Y - touch_y);
		spatial_dis = dis_x + dis_y;

		float touch_conf   =  expf((-(touch_dis) / 300.0f)) * 10;  //255
		//float spatial_conf =  expf((-(spatial_dis) / ((touch_conf) * 500))) * 10;
		float spatial_conf =  expf((-(spatial_dis) / 3000)) * 10;

		//p_sp->p_spix[si].salient_conf = 0.5 * spatial_dis * 0.4*touch_dis;
		p_sp->p_spix[si].salient_conf = spatial_conf * touch_conf;

		if (max_color_dis < p_sp->p_spix[si].salient_conf)
		{
			max_color_dis = p_sp->p_spix[si].salient_conf;
		}
		if (min_color_dis > p_sp->p_spix[si].salient_conf)
		{
			min_color_dis = p_sp->p_spix[si].salient_conf;
		}
	}

	float max_min = max_color_dis - min_color_dis;
	float avg_saliency = 0.0f;
	float salient_count = 1;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].salient_conf = 254 * (p_sp->p_spix[si].salient_conf - min_color_dis) / (float)(max_min);
		if (p_sp->p_spix[si].salient_conf > 0.01f)
		{
			salient_count++;
			avg_saliency += p_sp->p_spix[si].salient_conf;
		}
		//printf("salient_conf = %f\n", p_sp->p_spix[si].salient_conf);
	}
	avg_saliency /= salient_count;
	//printf("avg_saliency = %f\n", avg_saliency);

	float salient_th = avg_saliency * 2;
	if (salient_th > 200)
	{
		salient_th = 200;
	}
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		int size = win_size(p_sp->p_spix[si].win);
		if (p_sp->p_spix[si].salient_conf > avg_saliency && size < img_width * img_height * 0.4)
		{
			p_sp->p_spix[si].salient_conf = 255;
		}
		else
		{
			p_sp->p_spix[si].salient_conf = 0;
		}
	}

}



int create_candidate_box_by_graph(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int valid_s_pix_num, int touch_x, int touch_y)
{
	int count = 0;

	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	int* p_touch_neighbor_id_list = g_neighbor_matrix[touch_label];

	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].is_fg = false;
	}
	
	int  candidate_count = 0;
	for (int m = 0; m < valid_s_pix_num; m++)
	{
		if (p_touch_neighbor_id_list[m] > 0)
		{
			candidate_count++;
			p_sp->p_spix[m].is_fg = true;
		}
	}
	
	return candidate_count;
}

int create_candidate_box_by_four_feature(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int valid_s_pix_num, int touch_x, int touch_y, int iterate_count)
{

	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	compute_inter_conf(p_sp, valid_s_pix_num, touch_label);
	compute_color_conf(p_sp, valid_s_pix_num, touch_label);
	compute_spital_conf(p_sp, valid_s_pix_num, touch_x, touch_y, img_width, img_height, touch_label);
	computer_size_conf(p_sp, valid_s_pix_num, touch_label, img_width,  img_height);

	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].is_fg = false;
	}

	int first_vote_count = 1;
	float first_vote_avg_conf = 0.0f;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].conf = p_sp->p_spix[si].inter_conf * p_sp->p_spix[si].color_conf * p_sp->p_spix[si].dis_conf*p_sp->p_spix[si].size_conf;  //color_conf  dis_conf inter_conf  size_conf
		if (p_sp->p_spix[si].conf > 0 && p_sp->p_spix[si].is_bg == false)
		{
			//printf("candidate spix[%d] first 4 feature conf = %f\n", si, p_sp->p_spix[si].conf);
			first_vote_avg_conf += p_sp->p_spix[si].conf;
			first_vote_count++;
		}
	}
	first_vote_avg_conf /= (float)first_vote_count;
	//printf("first candidate vote_avg_conf = %f\n", first_vote_avg_conf);
	
	float second_vote_th = first_vote_avg_conf / 4.0f;  //3

	if (first_vote_count <= 2)
	{
		if (p_sp->p_spix[touch_label].conf > 0)
		{
			for (int i = 0; i < 4; i++)
			{
				p_sp->final_win[i] = p_sp->p_spix[touch_label].win[i];
			}
			p_sp->p_spix[touch_label].is_fg = true;
			return 1;
		}
		else
		{
			return 0;
		}
	}

	int second_vote_count = 0;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].conf > second_vote_th && p_sp->p_spix[si].is_bg == false)  //  /3
		{
			p_sp->p_spix[si].is_fg = true;
			second_vote_count++;
		}
		else
		{
			p_sp->p_spix[si].is_fg = false;
			p_sp->p_spix[si].conf  = 0.0f;
		}
	}

	float p_box_final[4] = {0};
	p_box_final[0] = img_width;
	p_box_final[1] = img_height;
	p_box_final[2] = -1;
	p_box_final[3] = -1;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_fg == true)
		{
			if (p_box_final[0] > p_sp->p_spix[si].win[0])
			{
				p_box_final[0] = p_sp->p_spix[si].win[0];
			}
			if (p_box_final[2] < p_sp->p_spix[si].win[2])
			{
				p_box_final[2] = p_sp->p_spix[si].win[2];
			}
			if (p_box_final[1] > p_sp->p_spix[si].win[1])
			{
				p_box_final[1] = p_sp->p_spix[si].win[1];
			}
			if (p_box_final[3] < p_sp->p_spix[si].win[3])
			{
				p_box_final[3] = p_sp->p_spix[si].win[3];
			}
		}
	}
	for (int i = 0; i < 4; i++)
	{
		p_sp->final_win[i] = p_box_final[i];
	}
	return second_vote_count;
}


int candidate_vote_by_four_feature(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int valid_s_pix_num = p_sp->valid_s_pix_num;
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	compute_inter_conf(p_sp,  valid_s_pix_num, touch_label);
	compute_color_conf(p_sp,  valid_s_pix_num, touch_label);
	compute_spital_conf(p_sp, valid_s_pix_num, touch_x, touch_y, img_width, img_height, touch_label);
	computer_size_conf(p_sp,  valid_s_pix_num, touch_label, img_width, img_height);

	int first_vote_count = 1;
	float first_vote_avg_conf = 0.0f;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].win_color[0] = 0;
		p_sp->p_spix[si].win_color[1] = 0;
		p_sp->p_spix[si].win_color[2] = 255;

		p_sp->p_spix[si].conf = p_sp->p_spix[si].inter_conf * p_sp->p_spix[si].color_conf * p_sp->p_spix[si].dis_conf*p_sp->p_spix[si].size_conf;  //color_conf  dis_conf inter_conf  size_conf
		if (p_sp->p_spix[si].conf > 0)
		{
			first_vote_avg_conf += p_sp->p_spix[si].conf;
			first_vote_count++;
		}
	}
	first_vote_avg_conf /= (float)first_vote_count;

	int second_vote_count = 0;
	float second_vote_th = first_vote_avg_conf / 4.0f;  //3
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].conf > second_vote_th)
		{
			p_sp->p_spix[si].vote_count++;
			second_vote_count++;
		}
	}
	return second_vote_count;
}

int create_init_box_by_four_feature(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	/*if (p_sp->layer_id < 2)
	{
		float touch_size_rate = (float)p_sp->p_spix[touch_label].size / (float)(img_width * img_height);
		if (touch_size_rate > 0.7)
		{
			for (int i = 0; i < 4; i++)
			{
				p_sp->final_win[i] = p_sp->p_spix[touch_label].win[i];
			}
			return 1;
		}
		int touch_win_width = p_sp->p_spix[touch_label].win[2] - p_sp->p_spix[touch_label].win[0] + 1;
		int touch_win_height = p_sp->p_spix[touch_label].win[3] - p_sp->p_spix[touch_label].win[1] + 1;
		if (touch_win_width > 0.9 * img_width || touch_win_height > 0.9 * img_height)
		{
			for (int i = 0; i < 4; i++)
			{
				p_sp->final_win[i] = p_sp->p_spix[touch_label].win[i];
			}
			return 1;
		}
	}*/

	//select candidate spix===========================================
	int  valid_s_pix_num    = p_sp->valid_s_pix_num;
	int  candidate_count    = create_candidate_box_by_four_feature(p_src_img, img_width, img_height, p_sp, valid_s_pix_num, touch_x, touch_y, 0);

	if (candidate_count <= 0)
	{
		//p_sp->is_low_contrast = 1;
		return 0;
	}
	else if (candidate_count <= 2)
	{

		return 1;
	}
	else
	{
		p_sp->final_win[0] = 0;
		p_sp->final_win[1] = 0;
		p_sp->final_win[2] = 0;
		p_sp->final_win[3] = 0;
	}

	//candidate spix vote=============================================
	int vote_count = 0;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_fg == true && p_sp->p_spix[si].is_bg == false)
		{
			int candidate_x = p_sp->p_spix[si].X;
			int candidate_y = p_sp->p_spix[si].Y;
			vote_count += candidate_vote_by_four_feature(p_src_img, img_width, img_height, p_sp, candidate_x, candidate_y);
		}
	}
	int avg_vote = (int)((float)vote_count / (float)candidate_count);

	//final election==========================================
	int election_th = avg_vote * 0.5;
	int width_th    = img_width  * 0.9f;
	int height_th   = img_height * 0.9f;
	int win_size_th = img_width  * img_height * 0.8f;
	int second_vote_count = 0;
	for (int si = 0; si < valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].vote_count > 0)
		{
			int size = win_size(p_sp->p_spix[si].win);
			if (size > win_size_th ||
				abs(p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0]) > width_th  ||
				abs(p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1]) > height_th)
				//p_sp->p_spix[si].is_bg)
			{
				p_sp->p_spix[si].is_fg = false;
			}
			else
			{
				p_sp->p_spix[si].is_fg = true;
				second_vote_count++;
			}
		}
		else
		{
			p_sp->p_spix[si].is_fg = false;;
		}
	}

	if (second_vote_count == 0)
	{
		return 0;
	}

	merge_candidate_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	return 1;
}

void create_init_box_by_graph(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{

	int img_size = img_width * img_height;
	int valid_s_pix_num = p_sp->valid_s_pix_num;
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	int* p_touch_neighbor_id_list = g_neighbor_matrix[touch_label];


	for (int si = 0; si < valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].is_fg = false;
		p_sp->p_spix[si].merge_id = si;
	}
	

	int touch_win_size = win_size(p_sp->p_spix[touch_label].win);
	p_sp->p_spix[touch_label].size_conf = (float)p_sp->p_spix[touch_label].size / (float)touch_win_size;
	if (p_sp->p_spix[touch_label].size_conf < 0.1)
	{
		p_sp->p_spix[touch_label].size_conf = 0.0f;
	}
	else if (touch_win_size > img_size * 0.9f)
	{
		p_sp->p_spix[touch_label].size_conf = 0.0f;
	}
	//if (p_sp->p_spix[touch_label].size_conf > 0.6 && p_sp->p_spix[touch_label].size > img_size * 0.002)
	//{
	//	for (int si = 0; si < valid_s_pix_num; si++)
	//	{
	//		p_sp->p_spix[si].size_conf = 0.0f;
	//	}
	//	p_sp->p_spix[touch_label].size_conf = 1.0f;
	//	p_sp->final_win[0] = p_sp->p_spix[touch_label].win[0];
	//	p_sp->final_win[1] = p_sp->p_spix[touch_label].win[1];
	//	p_sp->final_win[2] = p_sp->p_spix[touch_label].win[2];
	//	p_sp->final_win[3] = p_sp->p_spix[touch_label].win[3];
	//	p_sp->p_spix[touch_label].is_fg = true;
	//	p_sp->p_spix[touch_label].is_bg = false;
	//	return;
	//}

	int merge_count = 1;
	int merge_thres = 2000;
	int center_id = touch_label;
	int sum_color[3] = {p_sp->p_spix[touch_label].color.c0, p_sp->p_spix[touch_label].color.c1, p_sp->p_spix[touch_label].color.c2};
	p_sp->p_spix[touch_label].is_fg = true;

	touch_win_size = win_size(p_sp->p_spix[touch_label].win);
	p_sp->p_spix[touch_label].size_conf = (float)p_sp->p_spix[touch_label].size / (float)touch_win_size;
	if (p_sp->p_spix[touch_label].size_conf < 0.1)
	{
		p_sp->p_spix[touch_label].size_conf = 0;
		p_sp->p_spix[touch_label].win[0] = 0;
		p_sp->p_spix[touch_label].win[1] = 0;
		p_sp->p_spix[touch_label].win[2] = 0;
		p_sp->p_spix[touch_label].win[3] = 0;
		p_sp->final_win[0] = 0;
		p_sp->final_win[1] = 0;
		p_sp->final_win[2] = 0;
		p_sp->final_win[3] = 0;
		p_sp->is_low_contrast = 1;
		return;
	}


	for (int ci	= 0; ci < merge_count; ci++)
	{
		int avg_color[3];
		avg_color[0] = (float)sum_color[0] / (float)merge_count;
		avg_color[1] = (float)sum_color[1] / (float)merge_count;
		avg_color[2] = (float)sum_color[2] / (float)merge_count;

		//avg_color[0] = (float)sum_color[0] / (float)1;
		//avg_color[1] = (float)sum_color[1] / (float)1;
		//avg_color[2] = (float)sum_color[2] / (float)1;

		float min_dis = 9999999;
		int min_dis_id  = -1;
		for (int si = 0; si < valid_s_pix_num; si++)
		{
			S_Pix* p_spix = &p_sp->p_spix[si];
			if (g_neighbor_matrix[center_id][si] > 0 && /*p_spix->is_bg == false &&*/ p_spix->is_fg == false)
			{
				
				int color_dis = (p_spix->color.c0 - avg_color[0]) * (p_spix->color.c0 - avg_color[0]) * COLOR_MODIFY_RATE + 
							    (p_spix->color.c1 - avg_color[1]) * (p_spix->color.c1 - avg_color[1]) + 
							    (p_spix->color.c2 - avg_color[2]) * (p_spix->color.c2 - avg_color[2]);
				//if (color_dis > 600)
				//{
				//	continue;
				//}

				int s_win_size = win_size(p_spix->win);
				float s_win_size_conf = (float)p_spix->size / (float)s_win_size;
				if (s_win_size_conf < 0.1)
				{
					continue;
				}

				float dis_conf = distance_conf(p_spix->X, p_sp->p_spix[touch_label].X, p_spix->Y, p_sp->p_spix[touch_label].Y, img_width, img_height);
				if (dis_conf == 0)
				{
					continue;
				}


				int salient_conf = p_sp->p_spix[si].salient_conf;


				float final_dis = color_dis;

				//printf("final_dis = %f\n", final_dis);
				if (final_dis < min_dis )
				{
					min_dis = final_dis;
					min_dis_id  = si;
				}
			}
		}

		
		if (min_dis < merge_thres)
		{
			//printf("min_dis = %f\n", min_dis);
			p_sp->p_spix[min_dis_id].is_fg = true;

			sum_color[0] += p_sp->p_spix[min_dis_id].color.c0;
			sum_color[1] += p_sp->p_spix[min_dis_id].color.c1;
			sum_color[2] += p_sp->p_spix[min_dis_id].color.c2;

			center_id = min_dis_id;
			merge_count++;
		}
	}

	merge_candidate_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

}


void fill_rough_map_to_spix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int img_size = img_width * img_height;
	int linebyte24bit = img_width * 3;
	int offset = 256 / HIST_BIN_NUM;

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].salient_conf = 0;;

	}
	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			p_sp->p_spix[si].salient_conf += g_p_rough_map[index + 0];
		}
	}
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width + touch_x];
	
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		int   win_w       = p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0] + 1;
		int   win_h       = p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1] + 1;
		float win_respect = (float)win_w / (float)win_h;
		int   win_size    = win_w * win_h;
		float win_conf    = (float)p_sp->p_spix[si].size / (float)win_size;
		if (win_respect > 7.0f || 
			win_respect < 0.1f || 
			win_w < img_width * 0.01 ||
			win_h < img_height * 0.01  ||
			win_size < img_size * 0.0001 ||
			win_w > img_width * 0.9 ||
			win_h > img_height * 0.9 ||
			p_sp->p_spix[si].is_bg ||
			p_sp->p_spix[si].size <= S_PIX_MIN_SIZE ||
			win_conf < 0.1)
		{
			p_sp->p_spix[si].salient_conf = 0.0f;
		}
		else
		{
			p_sp->p_spix[si].salient_conf = (int)((float)p_sp->p_spix[si].salient_conf / (float)(p_sp->p_spix[si].size) + 0.5f);
		}
	}

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].salient_conf;
		}
	}
}


void fill_af_map_to_spix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int linebyte24bit = img_width * 3;
	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].color.c3;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].color.c3;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].color.c3;
		}
	}
}

void rank_auto_box_by_salient_conf(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int img_size = img_width * img_height;
	int linebyte24bit = img_width * 3;
	int offset = 256 / HIST_BIN_NUM;
	int max_salient_id[INIT_SALIENT_NUM]   = {-1};
	float max_salient_conf[INIT_SALIENT_NUM] = {-1};
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width + touch_x];

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_bg)
		{
			continue;
		}

		if (p_sp->p_spix[si].size < S_PIX_MIN_SIZE)
		{
			continue;
		}

		int   win_w       = p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0];
		int   win_h       = p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1];
		float win_respect = (float)win_w / (float)win_h;
		int   win_size    = win_w * win_h;
		//printf("respect[%d] size_conf = %f\n", si, respect);
		if (win_respect > 7.0f || 
			win_respect < 0.1f || 
			win_w < img_width * 0.01 ||
			win_h < img_height * 0.01  ||
			win_size < img_size * 0.0001 ||
			win_w > img_width * 0.9 ||
			win_h > img_height * 0.9)
		{
			continue;
		}



		for (int i = 0; i < INIT_SALIENT_NUM; i++)
		{
			int c0 = p_sp->p_spix[si].color.c0 / offset;
			int c1 = p_sp->p_spix[si].color.c1 / offset;
			int c2 = p_sp->p_spix[si].color.c2 / offset;

			float conf = (float)p_sp->p_spix[si].salient_conf;
			//float conf = (float)(g_back_size - g_p_back_hist[c0][c1][c2]) * (float)p_sp->p_spix[si].salient_conf / (float)(g_back_size) ;
			//conf = 1000.0f * (float)p_sp->p_spix[si].size / (float)((255 - conf) * (255 - conf) * (255 - conf) * (255 - conf)* (255 - conf)* (255 - conf));

			if (max_salient_conf[i] < conf)
			{
				for (int m = INIT_SALIENT_NUM - 1; m > i; m--)
				{
					max_salient_conf[m] = max_salient_conf[m - 1]; 
					max_salient_id[m]   = max_salient_id[m - 1]; 
				}
				max_salient_conf[i] = conf;
				max_salient_id[i]   = si;
				break;
			}
		}
	}

	
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[i].salient_conf = 0;
	}


	int le = p_sp->p_spix[touch_label].salient_conf;
	for (int i = 0; i < INIT_SALIENT_NUM; i++)
	{
		int id = max_salient_id[i];
		if (id > 0 && max_salient_conf[i] > 0)
		{
			p_sp->p_spix[id].salient_conf = max_salient_conf[i];
		}
	}
}

void computer_center_surrounf_conf(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp)
{
	int max_dis = -1, min_dis = 9999999;
	for (int center_id = 0; center_id < p_sp->valid_s_pix_num; center_id++)
	{
		S_Pix* p_center_spix = &p_sp->p_spix[center_id];

		if (p_center_spix->is_bg || p_center_spix->size < 20)
		{
			p_center_spix->cs_conf = 0;
			continue;
		}

		int c_color[3] = {p_center_spix->color.c0, p_center_spix->color.c1, p_center_spix->color.c2};
		int color_dis[3] = {0, 0, 0};
		int neighbor_count = 1;
		int final_dis = 0;
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			S_Pix* p_surround_spix = &p_sp->p_spix[si];
			if (g_neighbor_matrix[center_id][si] > 0)
			{
				int s_color[3] = {p_surround_spix->color.c0, p_surround_spix->color.c1, p_surround_spix->color.c2};

				int channel_0_dis = (s_color[0] - c_color[0]) * (s_color[0] - c_color[0]); 
				int channel_1_dis = (s_color[1] - c_color[1]) * (s_color[1] - c_color[1]); 
				int channel_2_dis = (s_color[2] - c_color[2]) * (s_color[2] - c_color[2]); 
				int all_channel_dis = channel_0_dis + channel_1_dis + channel_2_dis;

				if (all_channel_dis > 1000) //1000
				{
					color_dis[0] += channel_0_dis; 
					color_dis[1] += channel_1_dis; 
					color_dis[2] += channel_2_dis; 
					neighbor_count++;
				}
				
			}
		}

		color_dis[0] = (float)color_dis[0] / (float)neighbor_count;
		color_dis[1] = (float)color_dis[1] / (float)neighbor_count;
		color_dis[2] = (float)color_dis[2] / (float)neighbor_count;
		final_dis = color_dis[0] * COLOR_MODIFY_RATE + color_dis[1] + color_dis[2];

		if (final_dis < 0)
		{
			int sun = 0;
		}
		if (max_dis < final_dis)
		{
			max_dis = final_dis;
		}
		if (min_dis > final_dis)
		{
			min_dis = final_dis;
		}
		p_center_spix->cs_conf = final_dis;
	}

	int max_min = max_dis - min_dis;
	if (max_min > 0)
	{
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (p_sp->p_spix[si].is_bg == false && p_sp->p_spix[si].size > 20)
			{
				p_sp->p_spix[si].cs_conf = 255.0f * (float)(p_sp->p_spix[si].cs_conf - min_dis) / (float)(max_min);
			}
			else
			{
				p_sp->p_spix[si].cs_conf = 0;
			}
		}
	}

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].cs_conf < 0)
		{
			int sun = 0;
		}
	}
	

}

void get_help_from_auto_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{

	int min_dis = 99999999;
	int min_id  = 0;
	for (int i = 0; i < g_candidate_num; i++)
	{
		/*int c_id = g_candidate_id[i];
		S_Pix* p_c_spix = &p_sp->p_spix[c_id];
		int dis_x = (p_sp->p_spix[c_id].X - touch_x) * (p_sp->p_spix[c_id].X - touch_x);
		int dis_y = (p_sp->p_spix[c_id].Y - touch_y) * (p_sp->p_spix[c_id].Y - touch_y);*/

		int candidate_X = (g_candidate_win[i][0] + g_candidate_win[i][2]) / 2;
		int candidate_Y = (g_candidate_win[i][1] + g_candidate_win[i][3]) / 2;
		int dis_x = (candidate_X - touch_x) * (candidate_X - touch_x);
		int dis_y = (candidate_Y - touch_y) * (candidate_Y - touch_y);
		int spatial_dis = dis_x + dis_y;

		if (spatial_dis < min_dis)
		{ 
			min_dis = spatial_dis;
			min_id  = i;
		}
	}

	p_sp->final_win[0] = g_candidate_win[min_id][0];
	p_sp->final_win[1] = g_candidate_win[min_id][1];
	p_sp->final_win[2] = g_candidate_win[min_id][2];
	p_sp->final_win[3] = g_candidate_win[min_id][3];


	//short p_box_final[4] = {0};
	//p_box_final[0] = img_width;
	//p_box_final[1] = img_height;
	//p_box_final[2] = -1;
	//p_box_final[3] = -1;
	//for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	//{
	//	if (p_sp->p_spix[si].is_fg == true && p_sp->p_spix[si].is_bg == false)
	//	{
	//		if (p_box_final[0] > p_sp->p_spix[si].win[0])
	//		{
	//			p_box_final[0] = p_sp->p_spix[si].win[0];
	//		}
	//		if (p_box_final[2] < p_sp->p_spix[si].win[2])
	//		{
	//			p_box_final[2] = p_sp->p_spix[si].win[2];
	//		}
	//		if (p_box_final[1] > p_sp->p_spix[si].win[1])
	//		{
	//			p_box_final[1] = p_sp->p_spix[si].win[1];
	//		}
	//		if (p_box_final[3] < p_sp->p_spix[si].win[3])
	//		{
	//			p_box_final[3] = p_sp->p_spix[si].win[3];
	//		}
	//	}
	//}
	//for (int i = 0; i < 4; i++)
	//{
	//	p_sp->final_win[i] = p_box_final[i];
	//}

}



void merge_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y, float th)
{
	for (int i = 0; i < g_candidate_num; i++)
	{
		for (int j = 0; j < g_candidate_num; j++)
		{
			g_box_merge_matrix[i][j] = intersection_conf(g_candidate_win[i], g_candidate_win[j]);
		}
	}


	for (int i = 0; i < g_candidate_num; i++)
	{
		for (int j = 0; j < g_candidate_num; j++)
		{
			if (g_box_merge_matrix[i][j] > th)
			{
				short p_box_final[4] = {0};
				p_box_final[0] = img_width;
				p_box_final[1] = img_height;
				p_box_final[2] = -1;
				p_box_final[3] = -1;
				
				if (p_box_final[0] > g_candidate_win[i][0])
				{
					p_box_final[0] = g_candidate_win[i][0];
				}
				if (p_box_final[2] < g_candidate_win[i][2])
				{
					p_box_final[2] = g_candidate_win[i][2];
				}
				if (p_box_final[1] > g_candidate_win[i][1])
				{
					p_box_final[1] = g_candidate_win[i][1];
				}
				if (p_box_final[3] < g_candidate_win[i][3])
				{
					p_box_final[3] = g_candidate_win[i][3];
				}


				if (p_box_final[0] > g_candidate_win[j][0])
				{
					p_box_final[0] = g_candidate_win[j][0];
				}
				if (p_box_final[2] < g_candidate_win[j][2])
				{
					p_box_final[2] = g_candidate_win[j][2];
				}
				if (p_box_final[1] > g_candidate_win[j][1])
				{
					p_box_final[1] = g_candidate_win[j][1];
				}
				if (p_box_final[3] < g_candidate_win[j][3])
				{
					p_box_final[3] = g_candidate_win[j][3];
				}
				
				for (int m = 0; m < 4; m++)
				{
					g_candidate_win[i][m] = p_box_final[m];
					g_candidate_win[j][m] = p_box_final[m];
				}
			}
		}
	}
	
}


void refine_box_position(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
    int k;
    int x, y;
    int left, right, top, bottom;
    int x_shift = -1, y_shift = -1;
    int sum;
    int center_x = 0, center_y = 0;
    int index = 0;
    
    k = 0;
    center_x = 0;
    center_y = 0;
    sum = 0;
	left   = p_sp->final_win[0];
    right  = p_sp->final_win[2];
    top    = p_sp->final_win[1];
    bottom = p_sp->final_win[3];

    for (y = top; y <= bottom; y++)
    {
        for (x = left; x <= right; x++)
        {
            index = y * img_width * 3 + x * 3;
			center_x += x * g_p_rough_map[index];
            center_y += y * g_p_rough_map[index];
            sum += g_p_rough_map[index];
        }
    }

    if (sum > 0) {
        
        center_x = (((center_x << 1) / sum) + 1) >> 1; // round-off
        center_y = (((center_y << 1) / sum) + 1) >> 1; // round-off
        
        x_shift = center_x - ((p_sp->final_win[2] + p_sp->final_win[0] + 1) >> 1);
        y_shift = center_y - ((p_sp->final_win[3] + p_sp->final_win[1] + 1) >> 1);
        
        p_sp->final_win[0] += x_shift;
        p_sp->final_win[2] += x_shift;
        p_sp->final_win[1] += y_shift;
        p_sp->final_win[3] += y_shift;

		if (p_sp->final_win[0] > img_width - 2)
		{
			p_sp->final_win[0] = img_width - 2;

		}
		else if(p_sp->final_win[0] <= 0)
		{
			p_sp->final_win[0] = 0;
		}

		if (p_sp->final_win[2] > img_width - 2)
		{
			p_sp->final_win[2] = img_width - 2;
		}
		else if(p_sp->final_win[2] <= 0)
		{
			p_sp->final_win[2] = 0;
		}

		if (p_sp->final_win[1] > img_height - 2)
		{
			p_sp->final_win[1] = img_height - 2;
		}
		else if(p_sp->final_win[1] <= 0)
		{
			p_sp->final_win[1] = 0;
		}


		if (p_sp->final_win[3] > img_height - 2)
		{
			p_sp->final_win[3] = img_height - 2;
		}
		else if(p_sp->final_win[3] <= 0)
		{
			p_sp->final_win[3] = 0;
		}
	}


}


void create_box_automatically(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	
	rank_auto_box_by_salient_conf(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	int candidate_count    = 1;
	float avg_salient_conf = 0.0f;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		if (p_sp->p_spix[i].salient_conf > 0)
		{
			avg_salient_conf += p_sp->p_spix[i].salient_conf;
			candidate_count++;
		}
	}
	avg_salient_conf /= (float)candidate_count;

	g_candidate_num = 0;
	//printf("avg_salient_conf = %f\n", avg_salient_conf);
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		if (p_sp->p_spix[i].salient_conf > avg_salient_conf * 0.5f)
		{
			//create_init_box_by_graph(p_src_img, img_width, img_height, p_sp, p_sp->p_spix[i].X, p_sp->p_spix[i].Y);
			//create_init_box_by_four_feature(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
			//g_candidate_win[candidate_count][0] = p_sp->final_win[0];
			//g_candidate_win[candidate_count][1] = p_sp->final_win[1];
			//g_candidate_win[candidate_count][2] = p_sp->final_win[2];
			//g_candidate_win[candidate_count][3] = p_sp->final_win[3];

			g_candidate_win[g_candidate_num][0] = p_sp->p_spix[i].win[0];
			g_candidate_win[g_candidate_num][1] = p_sp->p_spix[i].win[1];
			g_candidate_win[g_candidate_num][2] = p_sp->p_spix[i].win[2];
			g_candidate_win[g_candidate_num][3] = p_sp->p_spix[i].win[3];

			g_candidate_id[g_candidate_num] = i;
			g_candidate_num++;
		}
		else
		{
			p_sp->p_spix[i].salient_conf = 0.0f;
		}
	}
	//merge_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, 0.2);
	//merge_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, 0.5);
}

void computer_socre_for_final_win(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	
	float avg_salient_conf = 0.0f;
	int salient_count = 1;
	int image_size = img_width * img_height;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf > BAYES_THRES && p_sp->p_spix[si].is_bg == false)
		{
			avg_salient_conf += p_sp->p_spix[si].salient_conf;
			salient_count++;
		}
	}
	avg_salient_conf = avg_salient_conf / (float)salient_count;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf < avg_salient_conf || p_sp->p_spix[si].is_bg)
		{
			p_sp->p_spix[si].salient_conf = 0;
		}
	}
	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * img_width * 3 + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].salient_conf;
		}
	}


}


int refine_box_size_and_position_by_mspix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	float avg_salient_conf = 0.0f;
	int salient_count = 1;
	int image_size = img_width * img_height;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf > BAYES_THRES && p_sp->p_spix[si].is_bg == false)
		{
			avg_salient_conf += p_sp->p_spix[si].salient_conf;
			salient_count++;
		}
	}
	avg_salient_conf = avg_salient_conf / (float)salient_count;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf < avg_salient_conf || p_sp->p_spix[si].is_bg)
		{
			p_sp->p_spix[si].salient_conf = 0;
		}
	}
		

	short p_fg_box[4]; 
	p_fg_box[0] = p_sp->final_win[0];
	p_fg_box[1] = p_sp->final_win[1];
	p_fg_box[2] = p_sp->final_win[2];
	p_fg_box[3] = p_sp->final_win[3];
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		float intersection = coverage_between_2boxs(p_fg_box, p_sp->p_spix[si].win);
		if (intersection < 0.2)
		{
			p_sp->p_spix[si].salient_conf = 0;
		}
	}

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * img_width * 3 + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].salient_conf;
		}
	}

	short p_box_final[4] = {0};
	p_box_final[0] = img_width;
	p_box_final[1] = img_height;
	p_box_final[2] = -1;
	p_box_final[3] = -1;
	int good_box_count = 0;

	int low_con_offset = 5 * (3 - p_sp->layer_id) * 2;
	if (p_sp->layer_id == 2)
	{
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (p_sp->p_spix[si].salient_conf <= avg_salient_conf || p_sp->p_spix[si].is_bg)
			{
				continue;
			}
			float w_size   = win_size(p_sp->p_spix[si].win); 
			float w_width  = p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0];
			float w_height = p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1];
			if (w_size > image_size * 0.9f)
			{
				continue;
			}
			if (w_width > 0.9 * img_width)
			{
				continue;
			}
			if (w_height > 0.9 * img_height)
			{
				continue;
			}

			if (p_box_final[0] > p_sp->p_spix[si].win[0])
			{
				p_box_final[0] = p_sp->p_spix[si].win[0];
			}
			if (p_box_final[2] < p_sp->p_spix[si].win[2])
			{
				p_box_final[2] = p_sp->p_spix[si].win[2];
			}
			if (p_box_final[1] > p_sp->p_spix[si].win[1])
			{
				p_box_final[1] = p_sp->p_spix[si].win[1];
			}
			if (p_box_final[3] < p_sp->p_spix[si].win[3])
			{
				p_box_final[3] = p_sp->p_spix[si].win[3];
			}
			good_box_count++;
		}

		if (good_box_count > 0)
		{
			for (int i = 0; i < 4; i++)
			{
				p_sp->final_win[i] = p_box_final[i];
			}
		}
		else
		{
			//p_sp->final_win[0] = touch_x - low_con_offset;
			//p_sp->final_win[1] = touch_y - low_con_offset;
			//p_sp->final_win[2] = touch_x + low_con_offset;
			//p_sp->final_win[3] = touch_y + low_con_offset;

			p_sp->final_win[0] = touch_x;
			p_sp->final_win[1] = touch_y;
			p_sp->final_win[2] = touch_x;
			p_sp->final_win[3] = touch_y;

		}
		//refine_box_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);


		return good_box_count;
	}
	else
	{
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (p_sp->p_spix[si].salient_conf <= avg_salient_conf )
			{
				continue;
			}

			if (p_box_final[0] > p_sp->p_spix[si].win[0])
			{
				p_box_final[0] = p_sp->p_spix[si].win[0];
			}
			if (p_box_final[2] < p_sp->p_spix[si].win[2])
			{
				p_box_final[2] = p_sp->p_spix[si].win[2];
			}
			if (p_box_final[1] > p_sp->p_spix[si].win[1])
			{
				p_box_final[1] = p_sp->p_spix[si].win[1];
			}
			if (p_box_final[3] < p_sp->p_spix[si].win[3])
			{
				p_box_final[3] = p_sp->p_spix[si].win[3];
			}
			good_box_count++;
		}

		if (good_box_count > 0)
		{
			for (int i = 0; i < 4; i++)
			{
				p_sp->final_win[i] = p_box_final[i];
			}
		}
		else
		{
			p_sp->final_win[0] = touch_x;
			p_sp->final_win[1] = touch_y;
			p_sp->final_win[2] = touch_x;
			p_sp->final_win[3] = touch_y;
		}
		//refine_box_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		return good_box_count;
	}
}






int refine_box_size_and_position(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	float avg_salient_conf = 0.0f;
	int salient_count = 1;
	int image_size = img_width * img_height;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf > BAYES_THRES && p_sp->p_spix[si].is_bg == false)
		{
			avg_salient_conf += p_sp->p_spix[si].salient_conf;
			salient_count++;
		}
	}
	avg_salient_conf = avg_salient_conf / (float)salient_count;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].salient_conf < avg_salient_conf || p_sp->p_spix[si].is_bg)
		{
			p_sp->p_spix[si].salient_conf = 0;
		}
	}

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * img_width * 3 + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].salient_conf;
		}
	}

	short p_box_final[4] = {0};
	p_box_final[0] = img_width;
	p_box_final[1] = img_height;
	p_box_final[2] = -1;
	p_box_final[3] = -1;
	int good_box_count = 0;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{

		if (p_sp->p_spix[si].salient_conf <= avg_salient_conf || p_sp->p_spix[si].is_bg)
		{
			continue;
		}
		float w_size   = win_size(p_sp->p_spix[si].win); 
		float w_width  = p_sp->p_spix[si].win[2] - p_sp->p_spix[si].win[0];
		float w_height = p_sp->p_spix[si].win[3] - p_sp->p_spix[si].win[1];
		if (w_size > image_size * 0.9f)
		{
			continue;
		}
		if (w_width > 0.9 * img_width)
		{
			continue;
		}
		if (w_height > 0.9 * img_height)
		{
			continue;
		}

		if (p_box_final[0] > p_sp->p_spix[si].win[0])
		{
			p_box_final[0] = p_sp->p_spix[si].win[0];
		}
		if (p_box_final[2] < p_sp->p_spix[si].win[2])
		{
			p_box_final[2] = p_sp->p_spix[si].win[2];
		}
		if (p_box_final[1] > p_sp->p_spix[si].win[1])
		{
			p_box_final[1] = p_sp->p_spix[si].win[1];
		}
		if (p_box_final[3] < p_sp->p_spix[si].win[3])
		{
			p_box_final[3] = p_sp->p_spix[si].win[3];
		}
		good_box_count++;
	}

	if (good_box_count > 0)
	{
		for (int i = 0; i < 4; i++)
		{
			p_sp->final_win[i] = p_box_final[i];
		}
	}
	else
	{
		p_sp->final_win[0] = touch_x - 9;
		p_sp->final_win[1] = touch_y - 9;
		p_sp->final_win[2] = touch_x + 9;
		p_sp->final_win[3] = touch_y + 9;

		// p_sp->final_win[0] = touch_x;
		// p_sp->final_win[1] = touch_y;
		// p_sp->final_win[2] = touch_x;
		// p_sp->final_win[3] = touch_y;


	}
	//refine_box_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	return good_box_count;
}




void create_distance_matrix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int img_size = img_width * img_height;

	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			g_p_distance_matrix[i][j] = 0;
		}
	}

	unsigned int avg_color[3] = {0, 0, 0};
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		if (p_sp->p_spix[i].size > 0)
		{
			avg_color[0] += p_sp->p_spix[i].color.c0 * p_sp->p_spix[i].size;
			avg_color[1] += p_sp->p_spix[i].color.c1 * p_sp->p_spix[i].size;
			avg_color[2] += p_sp->p_spix[i].color.c2 * p_sp->p_spix[i].size;
		}
	}
	avg_color[0] = (float)avg_color[0] / (float)img_size;
	avg_color[1] = (float)avg_color[1] / (float)img_size;
	avg_color[2] = (float)avg_color[2] / (float)img_size;


	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[i].color_conf = 0;
		if (p_sp->p_spix[i].size <= S_PIX_MIN_SIZE || p_sp->p_spix[i].is_bg == true)
		{
			continue;
		}
		int c_color[3] = {p_sp->p_spix[i].color.c0, p_sp->p_spix[i].color.c1, p_sp->p_spix[i].color.c2};
		int count = 1;
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			if (p_sp->p_spix[j].size <= S_PIX_MIN_SIZE || p_sp->p_spix[j].is_bg == false)
			{
				continue;
			}
			int s_color[3] 		= {p_sp->p_spix[j].color.c0, p_sp->p_spix[j].color.c1, p_sp->p_spix[j].color.c2};
			int channel_0_dis   = (s_color[0] - c_color[0]) * (s_color[0] - c_color[0]); 
			int channel_1_dis   = (s_color[1] - c_color[1]) * (s_color[1] - c_color[1]); 
			int channel_2_dis   = (s_color[2] - c_color[2]) * (s_color[2] - c_color[2]); 
			int all_channel_dis = channel_0_dis * COLOR_MODIFY_RATE + channel_1_dis + channel_2_dis; 

			p_sp->p_spix[i].color_conf += all_channel_dis;
			count++;
		}
		p_sp->p_spix[i].color_conf = (float)p_sp->p_spix[i].color_conf / (float)count;
	}

	int center_x = img_width >> 1;
	int center_y = img_height >> 1;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		S_Pix* p_center_spix = &p_sp->p_spix[i];
		//if (p_center_spix->size <= S_PIX_MIN_SIZE)
		//{
		//	continue;
		//}
		int dis_x = 0, dis_y = 0;
		int center_dis = 0, left_top_dis = 0, right_bottom_dis = 0;
		int c_color[3] = {p_center_spix->color.c0, p_center_spix->color.c1, p_center_spix->color.c2};

		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			if (i == j)
			{
				continue;
			}
			S_Pix* p_surround_spix = &p_sp->p_spix[j];
		
			if (p_surround_spix->size <= S_PIX_MIN_SIZE)
			{
				continue;
			}

			int s_color[3] = {p_surround_spix->color.c0, p_surround_spix->color.c1, p_surround_spix->color.c2};
			int channel_0_dis   = (s_color[0] - c_color[0]) * (s_color[0] - c_color[0]); 
			int channel_1_dis   = (s_color[1] - c_color[1]) * (s_color[1] - c_color[1]); 
			int channel_2_dis   = (s_color[2] - c_color[2]) * (s_color[2] - c_color[2]); 
			int all_channel_dis = channel_0_dis * COLOR_MODIFY_RATE + channel_1_dis + channel_2_dis; 

			//int avg_0_dis   = (c_color[0] - avg_color[0]) * (c_color[0] - avg_color[0]); 
			//int avg_1_dis   = (c_color[1] - avg_color[1]) * (c_color[1] - avg_color[1]); 
			//int avg_2_dis   = (c_color[2] - avg_color[2]) * (c_color[2] - avg_color[2]); 
			//int avg_dis = avg_0_dis + avg_1_dis + avg_2_dis; 




			int   win_w       = p_center_spix->win[2] - p_center_spix->win[0] + 1;
			int   win_h       = p_center_spix->win[3] - p_center_spix->win[1] + 1;
			float win_respect = (float)win_w / (float)win_h;
			int   win_size    = win_w * win_h;
			//float win_conf    = (float)p_center_spix->size / (float)win_size;
			//if (win_respect > 7.0f || 
			//	win_respect < 0.1f || 
			//	win_w < img_width * 0.01 ||
			//	win_h < img_height * 0.01  ||
			//	win_size < img_size * 0.0001 ||
			//	win_w > img_width * 0.9 ||
			//	win_h > img_height * 0.9 ||
			//	p_center_spix->is_bg ||
			//	win_conf < 0.1)
			//{
			//	win_conf = 0.0;
			//}
			//else
			//{
			//
			//}
			int size_id = (int)((sqrtf((float)win_size) * 4.0f) / 20.0);
			float win_conf = g_p_size_priori[size_id];

			float center_spatial_dis = 0.0f;
			dis_x = (p_center_spix->X - center_x) * (p_center_spix->X - center_x);   //p_surround_spix
			dis_y = (p_center_spix->Y - center_y) * (p_center_spix->Y - center_y);
			center_dis  = dis_x + dis_y;
			center_spatial_dis +=  expf((-(float)(center_dis) / 1000.f)); 
			
			dis_x = (p_center_spix->win[0] - center_x) * (p_center_spix->win[0] - center_x);
			dis_y = (p_center_spix->win[1] - center_y) * (p_center_spix->win[1] - center_y);
			left_top_dis = dis_x + dis_y;
			center_spatial_dis +=  expf((-(float)(left_top_dis) / 1000.f));

			dis_x = (p_center_spix->win[2] - center_x) * (p_center_spix->win[2] - center_x);
			dis_y = (p_center_spix->win[3] - center_y) * (p_center_spix->win[3] - center_y);
			right_bottom_dis = dis_x + dis_y;
			center_spatial_dis +=  expf((-(float)(right_bottom_dis) / 1000.f));



			//g_p_distance_matrix[i][j] = (float)intersection_conf( p_sp->p_spix[i].win, p_sp->p_spix[j].win) * ((float)all_ch annel_dis * p_sp->p_spix[i].salient_conf) * (float)p_center_spix->size / (float)(p_surround_spix->size); 
			//g_p_distance_matrix[i][j] = (float)all_channel_dis + (float)(p_sp->p_spix[i].salient_conf) * (float)p_center_spix->size / (float)(p_surround_spix->size); 
			float size_rate = (float)p_center_spix->size / (float)p_surround_spix->size;

			if (size_rate > 5.0f)
			{
				size_rate = 5.0f;
			}
			else if (size_rate < 0.1)
			{
				size_rate = 0.1;
			}
			//g_p_distance_matrix[i][j] =  spatial_dis * (float)all_channel_dis + (float)(p_sp->p_spix[i].salient_conf) * size_rate; 
			//g_p_distance_matrix[i][j] =  (float)all_channel_dis + (float)(p_sp->p_spix[i].salient_conf) * size_rate; 
			
			//g_p_distance_matrix[i][j] =  win_conf * center_spatial_dis * (float)all_channel_dis * (float)(p_sp->p_spix[i].salient_conf);  //size_rate
			g_p_distance_matrix[i][j] =  size_rate * center_spatial_dis * (float)all_channel_dis * (float)(p_sp->p_spix[i].salient_conf);  //size_rate
			//g_p_distance_matrix[i][j] =  win_conf * center_spatial_dis * (float)all_channel_dis;  //size_rate

		}
	}
	int sun = 0;
}

void create_clusters_matrix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			g_p_clusters_matrix[i][j] = g_p_distance_matrix[i][j] * g_p_fg_flag_array[i] * (1 - g_p_fg_flag_array[j]); 
		}
	}
}

void create_fg_bg_dis_matrix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int fg_count = (float)count_fg_number(p_sp);
	int bg_count = p_sp->valid_s_pix_num - fg_count;
	int non_zero_rate = (float)fg_count * (float)fg_count / (float)p_sp->valid_s_pix_num;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			g_p_fg_bg_dis_matrix[i][j] = g_p_distance_matrix[i][j] * g_p_fg_flag_array[i] * (1 - g_p_fg_flag_array[j]) + non_zero_rate; 
			//g_p_fg_bg_dis_matrix[i][j] = g_p_distance_matrix[i][j] + non_zero_rate; 
		}
	}
	int sun = 0;
}

void normailize_fg_bg_dis_matrix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	for (int j = 0; j < p_sp->valid_s_pix_num; j++)
	{
		float sum = 0;
		for (int i = 0; i < p_sp->valid_s_pix_num ; i++)
		{
			sum += g_p_fg_bg_dis_matrix[i][j]; 
		}
		if (sum > 0)
		{
			for (int i = 0; i < p_sp->valid_s_pix_num ; i++)
			{
				g_p_fg_bg_dis_matrix[i][j] /= sum; 
			}
		}

	}
	int sun = 0;
}

int salient_rank_energe(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int score = 0;
	unsigned int sum = 0;
	int count = 0;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			if (g_p_clusters_matrix[i][j] > 0)
			{
				sum += g_p_clusters_matrix[i][j] >> 1;
				count++;
			}
		}
	}
	if (count > 0)
	{
		score = (int)((float)(sum) / (float)count + 0.5f);
		//score = sum;
	}
	else
	{
		score = 0;
	}
	return score;
}





void choose_fg_to_bg_id(sp_output* p_sp, int img_width, int img_height, int* p_fg_to_bg, int* p_bg_to_fg)
{
	unsigned int min_value = 9999999999;
	int center_x = img_width  >> 1;
	int center_y = img_height >> 1;
	float dis_normail = 2000;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		for (int j = 0; j < p_sp->valid_s_pix_num; j++)
		{
			if (p_sp->p_spix[j].size <= S_PIX_MIN_SIZE || g_p_clusters_matrix[i][j] <= 0)
			{
				continue;
			}


			//float spatial_dis = 0.0f;
			//int dis_x = (p_sp->p_spix[j].X - center_x) * (p_sp->p_spix[j].X - center_x);
			//int dis_y = (p_sp->p_spix[j].Y - center_y) * (p_sp->p_spix[j].Y - center_y);
			//int center_dis  = dis_x + dis_y;
			//spatial_dis += expf((-(float)(center_dis) / dis_normail));
			//
			//dis_x = (p_sp->p_spix[j].win[0] - center_x) * (p_sp->p_spix[j].win[0] - center_x);
			//dis_y = (p_sp->p_spix[j].win[1] - center_y) * (p_sp->p_spix[j].win[1] - center_y);
			//int left_top_dis = dis_x + dis_y;
			//spatial_dis +=  expf((-(float)(left_top_dis) / dis_normail));

			//dis_x = (p_sp->p_spix[j].win[2] - center_x) * (p_sp->p_spix[j].win[2] - center_x);
			//dis_y = (p_sp->p_spix[j].win[3] - center_y) * (p_sp->p_spix[j].win[3] - center_y);
			//int right_bottom_dis = dis_x + dis_y;
			//spatial_dis +=  expf((-(float)(right_bottom_dis) / dis_normail));



			float conf = (float)g_p_clusters_matrix[i][j];
			if (conf < min_value)
			{
				min_value = conf;
				(*p_fg_to_bg) = i;
				(*p_bg_to_fg) = j;
			}
		}
	}
}




void init_salient_rank(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int offset = 256 / HIST_BIN_NUM;
	float fore_priority = 0.25;
	float back_priority = 1.0f - fore_priority;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		float fore_pro = 0.0f;
		if (p_sp->p_spix[i].is_bg == false && p_sp->p_spix[i].size > 0)
		{
			int c0 = p_sp->p_spix[i].color.c0 / offset;
			int c1 = p_sp->p_spix[i].color.c1 / offset;
			int c2 = p_sp->p_spix[i].color.c2 / offset;
			float fore_likehood = (float)g_p_fore_hist[c0][c1][c2] / (float)g_fore_size;
			float back_likehood = (float)g_p_back_hist[c0][c1][c2] / (float)g_back_size;
			float baye_conf = 0.0f;
			if (back_likehood <= 0.0f)
			{
				baye_conf = 1.0f;
			}
			else
			{
				baye_conf = (fore_likehood * fore_priority) / ((fore_likehood * fore_priority) + (back_likehood * back_priority));
			}
			fore_pro = 255.0f * baye_conf;

			if (fore_pro > 255)
			{
				fore_pro = 255;
			}
			else if (fore_pro < BAYES_THRES)
			{
				fore_pro = 0;
			}
		}
		p_sp->p_spix[i].salient_conf = fore_pro;
	}

	create_distance_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[i].rank = 0;
		g_p_rank_array[i] = -1;
		if (p_sp->p_spix[i].is_bg || p_sp->p_spix[i].size <= S_PIX_MIN_SIZE)
		{
			g_p_fg_flag_array[i] = 0;
		}
		else
		{
			g_p_fg_flag_array[i] = 1;
		}
	}
	create_clusters_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
}

int count_fg_number(sp_output* p_sp)
{
	int fg_count = 0;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		if (g_p_fg_flag_array[i])
		{
			fg_count++;
		}
	}
	return fg_count;
}


void sort_conf_vector(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	// g_p_rank_array[rank_count]  = fg_to_bg;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		g_p_rank_array[i] = i;
	}

	int fg_num = count_fg_number(p_sp);
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		float max_value = -1.0f;
		int   max_id    = -1.0f;
		for (int j = 1; j < p_sp->valid_s_pix_num - i; j++)
		{
			float left  = g_p_conf_vector[j - 1];
			float right = g_p_conf_vector[j];
			if (left > right)
			{
				float conf = g_p_conf_vector[j - 1];
				g_p_conf_vector[j - 1] = g_p_conf_vector[j];
				g_p_conf_vector[j]     = conf;

				float id = g_p_rank_array[j - 1];
				g_p_rank_array[j - 1] = g_p_rank_array[j];
				g_p_rank_array[j]     = id;
			}
		}
	}
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[g_p_rank_array[i]].rank = i;
	}
	int sun = 0;
}

void init_conf_vector(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	float salient_conf_sum = 0.0f;
	for (int i = 0; i < p_sp->valid_s_pix_num; ++i)
	{
		salient_conf_sum += p_sp->p_spix[i].salient_conf;
	}
	for (int i = 0; i < p_sp->valid_s_pix_num; ++i)
	{
		//g_p_conf_vector[i] = (float)(p_sp->p_spix[i].salient_conf + 1.0f) / (float)salient_conf_sum;
		g_p_conf_vector[i] = (float)(1.0f) / (float)p_sp->valid_s_pix_num;
	}
}


void update_conf_vector(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	float p_new_vector[S_PIX_NUM];
	for (int i = 0; i < p_sp->valid_s_pix_num; ++i)
	{
		p_new_vector[i] = 0;
		for (int j = 0; j < p_sp->valid_s_pix_num; ++j)
		{
			//if (p_sp->p_spix[j].size > 0 && p_sp->p_spix[j].is_bg == false)
			{
				p_new_vector[i] += g_p_conf_vector[j] * g_p_fg_bg_dis_matrix[i][j];
			}
		}
	}
	for (int i = 0; i < p_sp->valid_s_pix_num; ++i)
	{
		g_p_conf_vector[i] = p_new_vector[i];
	}
	int usn = 0;
}

int run_salient_rank(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	 int max_interation_num = 100000;
	 int debug[S_PIX_NUM] = {0};
	 int fg_to_bg = 0;
	 int bg_to_fg = 0;


	  init_salient_rank(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	  int init_fg_num = count_fg_number(p_sp);
	  if (init_fg_num < 5) //INIT_SALIENT_NUM
	  {
	 		return -1;
	  }

	  float show_rate = 255.0f / (float)init_fg_num;
	  int rank_count = 0;
	  int last_fg_to_bg_energe = 999999999;

	 
	  for (int i = 0; i < init_fg_num; i++)
	  {
	  	choose_fg_to_bg_id(p_sp, img_width, img_height, &fg_to_bg, &bg_to_fg);
	  	g_p_fg_flag_array[fg_to_bg] = 0;
	  	g_p_rank_array[rank_count]  = fg_to_bg;
	  	create_clusters_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	  	int energe = salient_rank_energe(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		p_sp->p_spix[fg_to_bg].rank = i;
	  	//printf("energe(%d) = %d\n", i, p_sp->p_spix[fg_to_bg].rank);
	  	rank_count++;
	  	if (energe <= 0)
	  	{
	  		break;
	  	}
	  }
	  return rank_count;







	 //init_salient_rank(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	 //int init_fg_num = count_fg_number(p_sp);
	 //if (init_fg_num < INIT_SALIENT_NUM)
	 //{
		// return -1;
	 //}/
	 //create_fg_bg_dis_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	 //normailize_fg_bg_dis_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	 //init_conf_vector(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	 //for (int i = 0; i < 3; i++)
	 //{
		// update_conf_vector(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	 //}

	 //sort_conf_vector(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	 //return p_sp->valid_s_pix_num;


}


void normalize_rank_socre(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{

	int max_rank = -1, min_rank = 99999999;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_bg || p_sp->p_spix[si].size <= S_PIX_MIN_SIZE)
		{
			continue;
		}

		if (max_rank < p_sp->p_spix[si].rank)
		{
			max_rank = p_sp->p_spix[si].rank;
		}
		if (min_rank > p_sp->p_spix[si].rank)
		{
			min_rank = p_sp->p_spix[si].rank;
		}
	}

	int max_min = max_rank - min_rank;
	if (max_min > 0)
	{
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			//p_sp->p_spix[si].rank = 255.0f * (float)(p_sp->p_spix[si].rank - min_rank) / (float)(max_min);


			if (p_sp->p_spix[si].is_bg == false && p_sp->p_spix[si].size > 0)
			{
				p_sp->p_spix[si].rank = 255.0f * (float)(p_sp->p_spix[si].rank - min_rank) / (float)(max_min);
			}
			else
			{
				p_sp->p_spix[si].rank = 0;
			}
		}
	}
}

void fill_rank_score_to_rough_map(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int linebyte24bit = 3 * img_width;
	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = 0;
			g_p_rough_map[index + 1] = 0;
			g_p_rough_map[index + 2] = 0;
		}
	}

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp->p_s_pix_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].rank;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].rank;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].rank;
		}
	}
}


void create_fixed_win(short* p_fixed_win, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y, float offset_rate)
{
	int x_offset = img_width  * offset_rate;
	int y_offset = img_height * offset_rate;
	

	p_fixed_win[0] = touch_x - x_offset;
	if (p_fixed_win[0] < 0)
	{
		p_fixed_win[0] = 0;
	}

	p_fixed_win[2] = touch_x + x_offset;
	if (p_fixed_win[2] > img_width - 1)
	{
		p_fixed_win[2] = img_width - 1;
	}

	p_fixed_win[1] = touch_y - y_offset;
	if (p_fixed_win[1] < 0)
	{
		p_fixed_win[1] = 0;
	}

	p_fixed_win[3] = touch_y + y_offset;
	if (p_fixed_win[3] > img_height - 1)
	{
		p_fixed_win[3] = img_height - 1;
	}
}

int set_fg_bg_flag_by_fixed_win(short* p_fixed_win, int img_width, int img_height, sp_output* p_sp, float conf_th)
{
	int fg_count = 0;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		short* p_spix_win  = p_sp->p_spix[si].win;
		float coverage_conf = coverage_between_2boxs(p_spix_win, p_fixed_win);
		if (p_sp->p_spix[si].is_bg == false && coverage_conf > conf_th)
		{
			p_sp->p_spix[si].is_fg = true;
			fg_count++;
		}
		else
		{
			p_sp->p_spix[si].is_bg = true;
		}
	}
	return fg_count;
}

int run_frameworkA(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
#ifdef _BACK_JUDGE_
	init_fg_bg_flag(p_sp);
	//if (p_sp->layer_id == 2)
	{
		run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	}
#endif


	int fg_count = 0;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_bg == false)
		{
			fg_count++;
		}
	}

	//printf("layer = %d, fg_count = %d\n", p_sp->layer_id, fg_count);
	short p_fixed_win[4];
	if (fg_count <= 10)
	{
		float conf_th = 0.2;
		float offset_rate = 0.1;
		create_fixed_win(p_fixed_win, img_width, img_height, p_sp, touch_x, touch_y, offset_rate);
		int fg_count = set_fg_bg_flag_by_fixed_win(p_fixed_win, img_width, img_height, p_sp, conf_th);
		int interate_count = 0;
		while(fg_count <= 0)
		{
			create_fixed_win(p_fixed_win, img_width, img_height, p_sp, img_width >> 1, img_height >> 1, offset_rate);
			init_fg_bg_flag(p_sp);
			run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
			fg_count = set_fg_bg_flag_by_fixed_win(p_fixed_win, img_width, img_height, p_sp, conf_th);
			conf_th *= 0.5;
			offset_rate *= 1.2;
			interate_count++;
			if (interate_count > 5 && fg_count == 0)
			{
				p_sp->final_win[0] = touch_x;
				p_sp->final_win[1] = touch_y;
				p_sp->final_win[2] = touch_x;
				p_sp->final_win[3] = touch_y;
				return 0;
			}
		}
		merge_candidate_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		return fg_count;
	}


#ifdef _LOW_CON_JUDGE_
	create_rough_map_by_spixel(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	fill_rough_map_to_spix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	low_contrast_judge(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
#else
	p_sp->is_low_contrast = 0;
#endif

	int box_state = 0;
	int low_con_offset = 10 * (3 - p_sp->layer_id) * 2;
	
	if (p_sp->is_low_contrast)
	{
		p_sp->final_win[0] = touch_x - low_con_offset;
		p_sp->final_win[1] = touch_y - low_con_offset;
		p_sp->final_win[2] = touch_x + low_con_offset;
		p_sp->final_win[3] = touch_y + low_con_offset;

		//p_sp->final_win[0] = 0;
		//p_sp->final_win[1] = 0;
		//p_sp->final_win[2] = 0;
		//p_sp->final_win[3] = 0;
		//return;
	}
	else
	{
		if (p_sp->layer_id != 2)
		{
			init_fg_bg_flag(p_sp);
		}
		//init_fg_bg_flag(p_sp);

		box_state = create_init_box_by_four_feature(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		//create_init_box_by_graph(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		if (box_state == 0)
		{
			p_sp->final_win[0] = touch_x - low_con_offset;
			p_sp->final_win[1] = touch_y - low_con_offset;
			p_sp->final_win[2] = touch_x + low_con_offset;
			p_sp->final_win[3] = touch_y + low_con_offset;

			//p_sp->final_win[0] = 0;
			//p_sp->final_win[1] = 0;
			//p_sp->final_win[2] = 0;
			//p_sp->final_win[3] = 0;
			//return;
		}
	}
#ifdef _REFINE_BOX_BY_ROUGH_MAP_
#ifdef _REFINE_BY_PIXEL_LEVEL_
	create_rough_map_by_init_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	fill_rough_map_to_spix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	refine_box_size_and_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	return 1;
#else
	create_rough_map_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, box_state);
	int is_ok = refine_box_size_and_position_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	return is_ok;
#endif	
#endif	
}




int choose_most_closed_auto_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int min_id  = 0;
	int min_dis = 9999999;
	for (int i = 0; i < g_candidate_num; i++)
	{
		int x0 = (g_candidate_win[i][0] + g_candidate_win[i][2]) / 2;
		int y0 = (g_candidate_win[i][1] + g_candidate_win[i][3]) / 2;
		int x1 = g_candidate_win[i][0];
		int y1 = g_candidate_win[i][1];
		int x2 = g_candidate_win[i][2];
		int y2 = g_candidate_win[i][3];

		int dis0 = (touch_x - x0) * (touch_x - x0) + (touch_y - y0) * (touch_y - y0); 
		int dis1 = (touch_x - x1) * (touch_x - x1) + (touch_y - y1) * (touch_y - y1);
		int dis2 = (touch_x - x2) * (touch_x - x2) + (touch_y - y2) * (touch_y - y2);
		int all_dis = dis0 + dis1 + dis2;
		if (all_dis < min_dis)
		{
			min_dis = all_dis;
			min_id  = i;
		}
	}
	return min_id;
}

int run_frameworkB(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{

#ifdef _OLD_FWB_
	//FrameworkB...
	init_fg_bg_flag(p_sp);
	run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	//int fg_num = create_affinity_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	//create_fundamental_matrix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, fg_num);
	//for (int y = 0; y < img_height; y++)
	//{
	//	for (int x = 0; x < img_width; x++)
	//	{
	//		int si = p_sp->p_s_pix_map[y * img_width + x];
	//		g_p_rough_map[y * img_width * 3 + x * 3 + 0] =  p_sp->p_spix[si].salient_conf;
	//		g_p_rough_map[y * img_width * 3 + x * 3 + 1] =  p_sp->p_spix[si].salient_conf;
	//		g_p_rough_map[y * img_width * 3 + x * 3 + 2] =  p_sp->p_spix[si].salient_conf;
	//	}
	//}
	
	short p_bg_box[4];
	create_bg_and_fg_hist_by_mspix(p_src_img, img_width, img_height, p_sp, p_bg_box);
	int rank_num = run_salient_rank(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	//printf("rank_num = %d\n", rank_num);
	normalize_rank_socre(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	fill_rank_score_to_rough_map(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	//init_fg_bg_flag(p_sp);
	g_candidate_num = 0;
	if (rank_num < 0)
	{
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (p_sp->p_spix[si].is_bg == false && p_sp->p_spix[si].size > 0)
			{
				g_candidate_win[g_candidate_num][0] = p_sp->p_spix[si].win[0];
				g_candidate_win[g_candidate_num][1] = p_sp->p_spix[si].win[1];
				g_candidate_win[g_candidate_num][2] = p_sp->p_spix[si].win[2];
				g_candidate_win[g_candidate_num][3] = p_sp->p_spix[si].win[3];
				g_candidate_num++;
			}
		}
	}
	else
	{
		for (int i = rank_num - 1; i > rank_num - 1 - INIT_SALIENT_NUM; i--)
		{
			if (g_p_rank_array[i] >= 0)
			{
				//int id = g_p_rank_array[i];
				//g_candidate_win[g_candidate_num][0] = p_sp->p_spix[id].win[0];
				//g_candidate_win[g_candidate_num][1] = p_sp->p_spix[id].win[1];
				//g_candidate_win[g_candidate_num][2] = p_sp->p_spix[id].win[2];
				//g_candidate_win[g_candidate_num][3] = p_sp->p_spix[id].win[3];

				bool init_box_is_ok = true;
				int id = g_p_rank_array[i];
				int new_x = p_sp->p_spix[id].X;
				int new_y = p_sp->p_spix[id].Y;
				int old_new_dis = 10000;
				//while(old_new_dis > 2)
				{
					int touch_x = new_x;
					int touch_y = new_y;
					int box_state = create_init_box_by_four_feature(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					if (box_state == 0)
					{
						init_box_is_ok = false;
						//break;;
					}
					//create_rough_map_by_init_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					//fill_rough_map_to_spix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					//refine_box_size_and_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					//new_x = new_x / 2 + (p_sp->final_win[2] + p_sp->final_win[0]) / 4;
					//new_y = new_y / 2 + (p_sp->final_win[3] + p_sp->final_win[1]) / 4;
					//old_new_dis = abs(new_x - touch_x) + abs(new_y - touch_y);

					create_rough_map_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, box_state);
					int init_box_is_ok = refine_box_size_and_position_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					return init_box_is_ok;
				}

				if (init_box_is_ok == true)
				{
					//computer_socre_for_final_win(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
					g_candidate_win[g_candidate_num][0] = p_sp->final_win[0];
					g_candidate_win[g_candidate_num][1] = p_sp->final_win[1];
					g_candidate_win[g_candidate_num][2] = p_sp->final_win[2];
					g_candidate_win[g_candidate_num][3] = p_sp->final_win[3];

					g_candidate_num++;
				}
			}
		}
	}
	//merge_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, 0.1);

	int id = choose_most_closed_auto_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	p_sp->final_win[0] = g_candidate_win[id][0];
	p_sp->final_win[1] = g_candidate_win[id][1];
	p_sp->final_win[2] = g_candidate_win[id][2];
	p_sp->final_win[3] = g_candidate_win[id][3];
#else


#ifdef _BACK_JUDGE_
	init_fg_bg_flag(p_sp);
	run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
#endif

	//====================================================================================================
	int fg_count = 0;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		if (p_sp->p_spix[si].is_bg == false)
		{
			fg_count++;
		}
	}
	short p_fixed_win[4];

	int fg_count_th = 10 * p_sp->layer_id;

	if (fg_count <= fg_count_th)
	{
		float conf_th = 0.2;
		float offset_rate = 0.1;

		create_fixed_win(p_fixed_win, img_width, img_height, p_sp, touch_x, touch_y, offset_rate);
		int fg_count = set_fg_bg_flag_by_fixed_win(p_fixed_win, img_width, img_height, p_sp, conf_th);
		int interate_count = 0;
		while(fg_count <= 0)
		{
			create_fixed_win(p_fixed_win, img_width, img_height, p_sp, img_width >> 1, img_height >> 1, offset_rate);
			init_fg_bg_flag(p_sp);
			run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
			fg_count = set_fg_bg_flag_by_fixed_win(p_fixed_win, img_width, img_height, p_sp, conf_th);
			conf_th *= 0.5;
			offset_rate *= 1.2;
			interate_count++;
			if (interate_count > 5 && fg_count == 0)
			{
				p_sp->final_win[0] = touch_x;
				p_sp->final_win[1] = touch_y;
				p_sp->final_win[2] = touch_x;
				p_sp->final_win[3] = touch_y;
				return 0;
			}
		}
		merge_candidate_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		return fg_count;
	}
	//====================================================================================================

	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		p_sp->p_spix[i].is_fg = false;
	}

	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	if (p_sp->p_spix[touch_label].is_bg)
	{
		int max_id  = 0;
		float max_coverage_rate = -1.0f;
		short p_fixed_win[4];
		create_fixed_win(p_fixed_win, img_width, img_height, p_sp, touch_x, touch_y, 0.1);
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (si != touch_label && p_sp->p_spix[si].is_bg == false)
			{
				float coverage_rate = coverage_between_2boxs(p_fixed_win, p_sp->p_spix[si].win);

				if (coverage_rate > max_coverage_rate)
				{
					max_coverage_rate = coverage_rate;
					max_id  = si;
				}
			}
		}
		touch_label = max_id;
	}
	p_sp->p_spix[touch_label].is_fg = true;
		

	int iteration_max_time = p_sp->valid_s_pix_num >> 1;
	int center_id = touch_label;
	for (int iterate_count= 0; iterate_count < iteration_max_time; iterate_count++)
	{
		int min_id  = -1;
		int min_dis = 9999999;
		for (int si = 0; si < p_sp->valid_s_pix_num; si++)
		{
			if (g_neighbor_matrix[center_id][si] > 0 && p_sp->p_spix[si].is_bg == false && p_sp->p_spix[si].is_fg == false)
			{
				int c_dis = color_dis(p_sp->p_spix[si].color.c0,        p_sp->p_spix[si].color.c1,        p_sp->p_spix[si].color.c2,
									  p_sp->p_spix[center_id].color.c0, p_sp->p_spix[center_id].color.c1, p_sp->p_spix[center_id].color.c2);

				//int s_dis = distance_dis(p_sp->p_spix[si].X, p_sp->p_spix[si].Y, p_sp->p_spix[center_id].X, p_sp->p_spix[center_id].Y, img_width, img_height);

				int dis = c_dis;

				if (dis < min_dis)
				{
					min_dis = dis;
					min_id  = si; 
				}
			}
		}

		if (min_id < 0)
		{
			break;
		}
		else if(min_dis > 100)
		{
			break;
		}
		else
		{
			p_sp->p_spix[min_id].is_fg = true;
			center_id = min_id;
		}
	}
	merge_candidate_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);

	int is_ok = 1;
	if (p_sp->final_win[2] - p_sp->final_win[0] < 50 && 
		p_sp->final_win[3] - p_sp->final_win[1] < 50)
	{
		is_ok = run_frameworkA(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	}

	//create_rough_map_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y, 1);
	//int is_ok = refine_box_size_and_position_by_mspix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	//return is_ok;

	return 1;
#endif



}





void run_frameworkAB(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	init_fg_bg_flag(p_sp);
	run_back_ground_classify(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	int touch_label = p_sp->p_s_pix_map[touch_y * img_width  + touch_x];

	int spix_box_ok = create_init_box_by_four_feature(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	if (spix_box_ok == 0)
	{
		run_frameworkB(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
	}
	else
	{
		create_rough_map_by_init_box(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		fill_rough_map_to_spix(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		int is_fwA_ok = refine_box_size_and_position(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		if (is_fwA_ok == 0)
		{
			run_frameworkB(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);
		}
	}
}


float computer_af_conf(unsigned char* p_af_map, int width, int height, short* p_win)
{
	int win_size = (p_win[2] - p_win[0]) * (p_win[3] - p_win[1]);
	if (win_size <= 0)
	{
		return 0.0f;
	}
	float af_conf = 0;
	for (int y = p_win[1]; y < p_win[3]; y++)
	{
		for (int x = p_win[0]; x < p_win[2]; x++)
		{
			af_conf += p_af_map[y * width * 3 + x * 3];
		}
	}
	af_conf /= (float)(win_size + 1);
	return af_conf;
}

int create_rough_map_and_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
#ifdef _FRAMEWORK_A_
	int is_ok = run_frameworkA(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);		
#endif

#ifdef _FRAMEWORK_B_ 
	int is_ok = run_frameworkB(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);		
#endif

#ifdef _FRAMEWORK_AB_
	run_frameworkAB(p_src_img, img_width, img_height, p_sp, touch_x, touch_y);	
#endif

#ifdef _FRAMEWORK_A_
	return is_ok;
#else
	return 1;
#endif
}

void background_classify_by_spix_position(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp)
{
	int y = 0, x = 0;
	int valid_s_pix_num = p_sp->valid_s_pix_num;

	short* p_label_map = p_sp->p_s_pix_map;

	int img_size = img_width * img_height;

	int back_size_th = 0.001 * img_size;

	int boundary_position = 3;

	y = boundary_position;
	int tmp_conf[S_PIX_NUM + 1] = {0};

	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		tmp_conf[i] = 0;
	}

	for (int x = 0; x < img_width; x++)
	{
		int si = p_label_map[y * img_width + x];
		//if (p_sp->p_spix[si].size > back_size_th)
		//{
		//	  p_sp->p_spix[si].is_bg = true;
		//}
		if (si >= 0 && si < p_sp->valid_s_pix_num)
		{
			tmp_conf[si]++;
		}
		else
		{
			int sun = 0;
		}
	}

	
	y = img_height - boundary_position - 1;
	for (int x = 0; x < img_width; x++)
	{
		int si = p_label_map[y * img_width + x];
		//if (p_sp->p_spix[si].size > back_size_th)
		//{
		//	p_sp->p_spix[si].is_bg = true;
		//}
		if (si >= 0 && si < p_sp->valid_s_pix_num)
		{
			tmp_conf[si]++;
		}
		else
		{
			int sun = 0;
		}
	}

	x = boundary_position;
	for (int y = 0; y < img_height; y++)
	{
		int si = p_label_map[y * img_width + x];
		//if (p_sp->p_spix[si].size > back_size_th)
		//{
		//	p_sp->p_spix[si].is_bg = true;
		//}
		if (si >= 0 && si < p_sp->valid_s_pix_num)
		{
			tmp_conf[si]++;
		}
		else
		{
			int sun = 0;
		}
	}

	x = img_width - boundary_position - 1;
	for (int y = 0; y < img_height; y++)
	{
		int si = p_label_map[y * img_width + x];
		//if (p_sp->p_spix[si].size > back_size_th)
		//{
		//	p_sp->p_spix[si].is_bg = true;
		//}
		if (si >= 0 && si < p_sp->valid_s_pix_num)
		{
			tmp_conf[si]++;
		}
		else
		{
			int sun = 0;
		}
	}

	int bg_count = 0;
	for (int i = 0; i < p_sp->valid_s_pix_num; i++)
	{
		if (tmp_conf[i] > img_width * 0.5 || 
			tmp_conf[i] > img_height * 0.5)
		{
			p_sp->p_spix[i].is_bg = true;
			bg_count++;
		}
	}
	if (bg_count == p_sp->valid_s_pix_num)
	{
		for (int i = 0; i < p_sp->valid_s_pix_num; i++)
		{
			p_sp->p_spix[i].is_bg = false;;
		}
	}

}

void set_bg_area(short *p_fg_area, short *p_bg_area, int image_width, int image_height, int scale)
{
	int p_fg_area_width  = p_fg_area[2] - p_fg_area[0] + 1;
	int p_fg_area_height = p_fg_area[3] - p_fg_area[1] + 1;
    int range = (int)(p_fg_area_width + p_fg_area_height) >> scale;
    p_bg_area[0] = p_fg_area[0] -  range;
    p_bg_area[1] = p_fg_area[1] -  range;
    p_bg_area[2] = p_bg_area[0] + (range * 4);
    p_bg_area[3] = p_bg_area[1] + (range * 4);
    if (p_bg_area[0] < 0)
    {
        p_bg_area[0] = 0;
    }
    if (p_bg_area[2] >= image_width)
    {
        p_bg_area[2] = image_width - 1;
    }
    if (p_bg_area[1] < 0)
    {
        p_bg_area[1] = 0;
    }
    if (p_bg_area[3] >= image_height)
    {
        p_bg_area[3] = image_height - 1;
    }
    return;
}

void create_bg_and_fg_hist_by_init_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, short* bg_box)
{
	for (int c0 = 0; c0 < HIST_BIN_NUM; c0 ++)
	{
		for (int c1 = 0; c1 < HIST_BIN_NUM; c1 ++)
		{
			for (int c2 = 0; c2 < HIST_BIN_NUM; c2 ++)
			{
				g_p_fore_hist[c0][c1][c2] = 0;
				g_p_back_hist[c0][c1][c2] = 0;
			}
		}
	}
	
	short fg_box[4]; 
	fg_box[0] = p_sp->final_win[0];
	fg_box[1] = p_sp->final_win[1];
	fg_box[2] = p_sp->final_win[2];
	fg_box[3] = p_sp->final_win[3];
	int fg_width  = fg_box[2] - fg_box[0] + 1;
	int fg_height = fg_box[3] - fg_box[1] + 1;

	set_bg_area(fg_box, bg_box, img_width, img_height, 2);

	int linebyte24bit = (img_width * 3 + 3) / 4 * 4;
	short* p_label_map = p_sp->p_s_pix_map;
	int offset = 256 / HIST_BIN_NUM;
	
	g_fore_size = 1;
	g_back_size = 1;
	for (int y = bg_box[1]; y < bg_box[3]; y++)
	{
		for (int x = bg_box[0]; x < bg_box[2]; x++)
		{
			int index = y * linebyte24bit + x * 3;
			int c0 = p_src_img[index + 0] / offset;
			int c1 = p_src_img[index + 1] / offset;
			int c2 = p_src_img[index + 2] / offset;

			if (x < fg_box[0] || 
				y < fg_box[1] || 
				x > fg_box[2] || 
				y > fg_box[3])
			{
				g_back_size++;
				g_p_back_hist[c0][c1][c2]++;
			}
			else
			{
				g_p_fore_hist[c0][c1][c2]++;
				g_fore_size++;
			}
		}
	}



}


void create_bg_and_fg_hist_by_mspix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, short* p_bg_box)
{
	for (int c0 = 0; c0 < HIST_BIN_NUM; c0 ++)
	{
		for (int c1 = 0; c1 < HIST_BIN_NUM; c1 ++)
		{
			for (int c2 = 0; c2 < HIST_BIN_NUM; c2 ++)
			{
				g_p_fore_hist[c0][c1][c2] = 0;
				g_p_back_hist[c0][c1][c2] = 0;
			}
		}
	}

	int offset = 256 / HIST_BIN_NUM;
	g_fore_size = 1;
	g_back_size = 1;
	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		int c0 = p_sp->p_spix[si].color.c0 / offset;
		int c1 = p_sp->p_spix[si].color.c1 / offset;
		int c2 = p_sp->p_spix[si].color.c2 / offset;

		int x = p_sp->p_spix[si].X;
		int y = p_sp->p_spix[si].Y;

		if (p_sp->p_spix[si].is_fg)
		{
			g_p_fore_hist[c0][c1][c2] += p_sp->p_spix[si].size;
			g_fore_size += p_sp->p_spix[si].size;
			
		}
		//else if (x > p_bg_box[0] && x < p_bg_box[2] && y > p_bg_box[1] && y < p_bg_box[3])

		float bg_intersection = coverage_between_2boxs(p_bg_box, p_sp->p_spix[si].win);
		if (bg_intersection > 0.3)
		{
			g_back_size += p_sp->p_spix[si].size;
			g_p_back_hist[c0][c1][c2] += p_sp->p_spix[si].size;
		}
	}
}


void create_rough_map_by_init_box(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	int valid_s_pix_num = p_sp->valid_s_pix_num;

	short p_bg_box[4];
	create_bg_and_fg_hist_by_init_box(p_src_img, img_width, img_height, p_sp, p_bg_box);

	int img_size = img_width * img_height;
	int linebyte24bit = (img_width * 3 + 3) / 4 * 4;
	short* p_label_map = p_sp->p_s_pix_map;
	int offset = 256 / HIST_BIN_NUM;

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = 0;
			g_p_rough_map[index + 1] = 0;
			g_p_rough_map[index + 2] = 0;
		}
	}

	int bg_size = (p_bg_box[2] - p_bg_box[0]) * (p_bg_box[3] - p_bg_box[1]);
	float fore_priority = (float)g_fore_size / (float)bg_size;
	float back_priority = 1.0f - fore_priority;

	for (int y = p_bg_box[1]; y < p_bg_box[3]; y++)
	{
		for (int x = p_bg_box[0]; x < p_bg_box[2]; x++)
		{
			int si = p_label_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			int c0 = p_src_img[index + 0] / offset;
			int c1 = p_src_img[index + 1] / offset;
			int c2 = p_src_img[index + 2] / offset;

			float fore_likehood = (float)g_p_fore_hist[c0][c1][c2] / (float)g_fore_size;
			float back_likehood = (float)g_p_back_hist[c0][c1][c2] / (float)g_back_size;
			float fore_pro = 0.0f;

			if (p_sp->p_spix[si].is_bg == false)
			{
				float baye_conf = 0.0f;
				if (back_likehood <= 0.0f)
				{
					baye_conf = 1.0f;
				}
				else
				{
					baye_conf = (fore_likehood * fore_priority) / ((fore_likehood * fore_priority) + (back_likehood * back_priority));
				}
				fore_pro = 255.0f * baye_conf;

				if (fore_pro > 255)
				{
					fore_pro = 255;
				}
				else if (fore_pro < BAYES_THRES)
				{
					fore_pro = 0;
				}
			}
			g_p_rough_map[index + 0] = fore_pro;
			g_p_rough_map[index + 1] = fore_pro;
			g_p_rough_map[index + 2] = fore_pro;
		}
	}
}



void create_rough_map_by_mspix(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y, int box_state)
{
	int valid_s_pix_num = p_sp->valid_s_pix_num;

	short p_fg_box[4] = {0};
	p_fg_box[0] = p_sp->final_win[0];
	p_fg_box[1] = p_sp->final_win[1];
	p_fg_box[2] = p_sp->final_win[2];
	p_fg_box[3] = p_sp->final_win[3];
	short p_bg_box[4] = {0};
	set_bg_area(p_fg_box, p_bg_box, img_width, img_height, 1);

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		p_sp->p_spix[si].is_fg = false;
	}

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		float fg_intersection = coverage_between_2boxs(p_fg_box, p_sp->p_spix[si].win);
		if (fg_intersection > 0.6)
		{
			p_sp->p_spix[si].is_fg = true;
		}
	}
	create_bg_and_fg_hist_by_mspix(p_src_img, img_width, img_height, p_sp, p_bg_box);

	int img_size = img_width * img_height;
	int linebyte24bit = (img_width * 3 + 3) / 4 * 4;
	short* p_label_map = p_sp->p_s_pix_map;
	int offset = 256 / HIST_BIN_NUM;
	
	float fore_priority = (float)g_fore_size / (float)img_size;
	float back_priority = 1.0f - fore_priority;

	for (int si = 0; si < p_sp->valid_s_pix_num; si++)
	{
		int c0 = p_sp->p_spix[si].color.c0 / offset;
		int c1 = p_sp->p_spix[si].color.c1 / offset;
		int c2 = p_sp->p_spix[si].color.c2 / offset;
		float fore_likehood = (float)g_p_fore_hist[c0][c1][c2] / (float)g_fore_size;
		float back_likehood = (float)g_p_back_hist[c0][c1][c2] / (float)g_back_size;
		float fore_pro = 0.0f;

		if (p_sp->p_spix[si].is_bg == false)
		{
			float baye_conf = 0.0f;
			if (back_likehood <= 0.0f)
			{
				baye_conf = 1.0f;
			}
			else
			{
				baye_conf = (fore_likehood * fore_priority) / ((fore_likehood * fore_priority) + (back_likehood * back_priority));
			}
			fore_pro = 255.0f * baye_conf;
			if (fore_pro > 255)
			{
				fore_pro = 255;
			}
			if (fore_pro > 0)
			{
				int sun = 0;
			}
			p_sp->p_spix[si].salient_conf = fore_pro;
		}
	}

	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_label_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			g_p_rough_map[index + 0] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 1] = p_sp->p_spix[si].salient_conf;
			g_p_rough_map[index + 2] = p_sp->p_spix[si].salient_conf;
		}
	}
}

void background_classify_by_win_size(sp_output* p_sp_out, unsigned char* p_src_img, int img_width, int img_height)
{
	int img_size = img_width * img_height;
	for (int si = 0; si < p_sp_out->valid_s_pix_num; si++)
	{
		if (p_sp_out->p_spix[si].is_bg == false && p_sp_out->p_spix[si].size > 0)
		{
			int   win_w       = p_sp_out->p_spix[si].win[2] - p_sp_out->p_spix[si].win[0];
			int   win_h       = p_sp_out->p_spix[si].win[3] - p_sp_out->p_spix[si].win[1];
			float win_respect = (float)win_w / (float)win_h;
			int   win_size    = win_w * win_h;
			float win_score   = (float)p_sp_out->p_spix[si].size / (float)win_size;
			//printf("respect[%d] size_conf = %f\n", si, respect);

			if (win_respect > 8.0f || 
				win_respect < 0.15f || 
				win_w < img_width * 0.01 ||
				win_h < img_height * 0.01 ||
				win_size < img_size * 0.0001||
				win_score < 0.1)
				//win_w > img_width * 0.9  ||
				//win_h > img_height * 0.9 ||
			{
				p_sp_out->p_spix[si].is_bg = true;
			}
		}
	}
}

void fill_src_image_to_spix(sp_output* p_sp_out, unsigned char* p_src_img, int img_width, int img_height)
{
	int linebyte24bit = img_width * 3;
	for (int si = 0; si < p_sp_out->valid_s_pix_num; si++)
	{
		p_sp_out->p_spix[si].color.c0 = 0;
		p_sp_out->p_spix[si].color.c1 = 0;
		p_sp_out->p_spix[si].color.c2 = 0;
		p_sp_out->p_spix[si].size     = 0;
	}
	for (int y = 0; y < img_height; y++)
	{
		for (int x = 0; x < img_width; x++)
		{
			int si = p_sp_out->p_s_pix_map[y * img_width + x];
			int index = y * linebyte24bit + x * 3;
			int c0 = p_src_img[index + 0];
			int c1 = p_src_img[index + 1];
			int c2 = p_src_img[index + 2];
			p_sp_out->p_spix[si].color.c0 += c0;
			p_sp_out->p_spix[si].color.c1 += c1;
			p_sp_out->p_spix[si].color.c2 += c2;
			p_sp_out->p_spix[si].size++;
		}
	}
	for (int si = 0; si < p_sp_out->valid_s_pix_num; si++)
	{
		p_sp_out->p_spix[si].color.c0 = (int)((float)p_sp_out->p_spix[si].color.c0 / (float)p_sp_out->p_spix[si].size + 0.5f);
		p_sp_out->p_spix[si].color.c1 = (int)((float)p_sp_out->p_spix[si].color.c1 / (float)p_sp_out->p_spix[si].size + 0.5f);
		p_sp_out->p_spix[si].color.c2 = (int)((float)p_sp_out->p_spix[si].color.c2 / (float)p_sp_out->p_spix[si].size + 0.5f);
	}
}



void background_classify_by_neighbor_info(sp_output* p_sp_out, int img_width, int img_height, int touch_x, int touch_y)
{
	float conf_array[S_PIX_NUM] = {0};

	short* p_s_pix_map  = p_sp_out->p_s_pix_map;
	int valid_s_pix_num = p_sp_out->valid_s_pix_num;
	S_Pix* p_sp         = p_sp_out->p_spix;

	for (int n = 0; n < valid_s_pix_num; n++)
	{
		for (int m = 0; m < valid_s_pix_num; m++)
		{
			if (g_neighbor_matrix[n][m] > 0)
			{
				conf_array[n] += 1;
			}
		}
	}

	float avg_conf = 0;
	float avg_count = 0;
	for (int m = 0; m < valid_s_pix_num; m++)
	{
		if (conf_array[m] > 0)
		{
			int box_size = win_size(p_sp_out->p_spix[m].win);
			conf_array[m] = ((float)conf_array[m]);
			avg_conf += conf_array[m];
			avg_count += 1;
		}
	}
	avg_conf =  8 * ((float)avg_conf / (float)avg_count);
	
	int touch_label = p_s_pix_map[touch_y * img_width + touch_x];
	//printf("touch conf   = %f\n", (float)conf_array[touch_label]);
	//printf("average conf = %f\n", avg_conf);

	if (valid_s_pix_num < 20)
	{
		return;
	}
	for (int m = 0; m < valid_s_pix_num; m++)
	{
		if (conf_array[m] <= avg_conf && conf_array[m] > 1)
		{
			//p_sp[m].is_bg = false;
		}
		else
		{
			p_sp[m].is_bg = true;
		}
	}
}



void low_contrast_judge(unsigned char* p_src_img, int img_width, int img_height, 
						sp_output* p_sp,          int touch_x,   int touch_y)
{
	
	short* p_s_pix_map = p_sp->p_s_pix_map;
	int linebyte24bit  =  img_width * 3;
	int touch_label = p_s_pix_map[touch_y * img_width + touch_x];

	if (p_sp->p_spix[touch_label].is_bg)
	{
		p_sp->is_low_contrast = 1;
		return;
	}


	short touch_spix_win[4];
	touch_spix_win[0] = p_sp->p_spix[touch_label].win[0];
	touch_spix_win[1] = p_sp->p_spix[touch_label].win[1];
	touch_spix_win[2] = p_sp->p_spix[touch_label].win[2];
	touch_spix_win[3] = p_sp->p_spix[touch_label].win[3];

	int avg_fore_pro   = 0;
	int touch_win_size = win_size(touch_spix_win);
	for (int y = touch_spix_win[1]; y < touch_spix_win[3]; y++)
	{
		for (int x = touch_spix_win[0]; x < touch_spix_win[2]; x++)
		{
			avg_fore_pro += g_p_rough_map[y * linebyte24bit + x * 3];
		}
	}
	avg_fore_pro = ((float)avg_fore_pro / (float)touch_win_size + 0.5f);

	p_sp->is_low_contrast = 0;
	if (avg_fore_pro < p_sp->low_con_thres)
	{
		p_sp->is_low_contrast = 1;
	}
}


void background_classify_by_color_distribution(sp_output* p_sp_out, unsigned char* p_src_img, int img_width, int img_height)
{
	for (int si = 0; si < p_sp_out->valid_s_pix_num; si++)
	{
		if (p_sp_out->p_spix[si].is_bg == true && p_sp_out->p_spix[si].size > 0)
		{
			if (p_sp_out->p_spix[si].color.c0 < 10)
			{
				p_sp_out->p_spix[si].is_bg = false;
			}
		}
	}
}

void run_back_ground_classify(unsigned char* p_src_img, int img_width, int img_height, sp_output* p_sp, int touch_x, int touch_y)
{
	background_classify_by_spix_position(p_src_img, img_width, img_height, p_sp);
	background_classify_by_win_size(p_sp, p_src_img, img_width, img_height);

	//background_classify_by_color_distribution(p_sp, p_src_img, img_width, img_height);

	//background_classify_by_neighbor_info(p_sp, img_width, img_height, touch_x, touch_y);
	//background_classify_by_bayesmap(p_src_img, img_width, img_height, p_sp, valid_s_pix_num, touch_x, touch_y);
	//fill_spix_color_by_src_image(p_sp, p_src_img, img_width, img_height);



}

